home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-30 | 935.3 KB | 31,236 lines |
- diff -rNci gcc-2.7.2/combine.c gcc-2.7.2p/combine.c
- *** gcc-2.7.2/combine.c Sun Nov 26 19:32:07 1995
- --- gcc-2.7.2p/combine.c Tue Jan 23 09:53:17 1996
- ***************
- *** 97,102 ****
- --- 97,106 ----
- #include "recog.h"
- #include "real.h"
-
- + /* intel1 */
- + static int in_recombine=0;
- + extern FILE *combine_dump_file;
- +
- /* It is not safe to use ordinary gen_lowpart in combine.
- Use gen_lowpart_for_combine instead. See comments there. */
- #define gen_lowpart dont_use_gen_lowpart_you_dummy
- ***************
- *** 386,391 ****
- --- 390,418 ----
-
- static int n_occurrences;
-
- + /* intel2 - begin */
- +
- + #define INSN_SETS_REGNO(INSN, REGNO) dead_or_set_regno_p (INSN, REGNO)
- + #define INSN_USES_REGNO(INSN, REGNO) refers_to_regno_p (REGNO, \
- + REGNO + 1, \
- + PATTERN (INSN), \
- + 0)
- +
- + /* if this flag is set do not recombine unscheded riscified insns, which their
- + * original insn's destination was a memory.
- + */
- + extern int flag_risc_mem_dest;
- +
- + /* if this flag is set try to riscify stores of CONST_INTs */
- + extern int flag_risc_const;
- +
- + void update_free_regs (rtx);
- + static void update_regno_holds_mem (rtx insn, rtx pat);
- + static int remove_redundant_store (rtx mem, int block);
- + static void update_entries (rtx reg);
- +
- + /* intel2 - end */
- +
- static void init_reg_last_arrays PROTO(());
- static void setup_incoming_promotions PROTO(());
- static void set_nonzero_bits_and_sign_copies PROTO((rtx, rtx));
- ***************
- *** 445,450 ****
- --- 472,486 ----
- static void distribute_notes PROTO((rtx, rtx, rtx, rtx, rtx, rtx));
- static void distribute_links PROTO((rtx));
- static void mark_used_regs_combine PROTO((rtx));
- + static int try_forwards_replace PROTO((rtx, rtx, rtx, FILE *));
- + /* intel2 */
- + #if 0
- + static void dump_free_registers ();
- + #endif
- + int find_free_reg();
- + static int find_regno_holds_mem (rtx, enum machine_mode);
- + /* intel1 */
- + static int try_backwards_replace ();
-
- /* Main entry point for combiner. F is the first insn of the function.
- NREGS is the first unused pseudo-reg number. */
- ***************
- *** 881,886 ****
- --- 917,925 ----
-
- /* Don't eliminate a store in the stack pointer. */
- if (dest == stack_pointer_rtx
- + /* intel1
- + || (in_recombine && GET_CODE (dest) == REG
- + && reg_used_between_p (dest, insn, i3)) */
- /* If we couldn't eliminate a field assignment, we can't combine. */
- || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART
- /* Don't combine with an insn that sets a register to itself if it has
- ***************
- *** 1059,1064 ****
- --- 1098,1105 ----
- On machines where SMALL_REGISTER_CLASSES is defined, we don't combine
- if the destination of a SET is a hard register that isn't a user
- variable.
- + intel2 - This is true unless we are in recombine (indicated by
- + in_recombine)
-
- Before doing the above check, we first try to expand a field assignment
- into a set of logical operations.
- ***************
- *** 1128,1139 ****
- --- 1169,1194 ----
- CALL operation. */
- || (GET_CODE (inner_dest) == REG
- && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER
- + /* intel2 - begin */
- + /* if we are in the recombine phase, we should not eliminate the
- + * possibility for combine if the destination is a hard register.
- + */
- + && (!in_recombine)
- + /* intel2 - end */
- && (! HARD_REGNO_MODE_OK (REGNO (inner_dest),
- GET_MODE (inner_dest))
- #ifdef SMALL_REGISTER_CLASSES
- || (GET_CODE (src) != CALL && ! REG_USERVAR_P (inner_dest))
- #endif
- ))
- +
- + /* intel2 - begin */
- + /* if we want to leave mem-dest riscified instructions untouched... */
- + || (in_recombine
- + && flag_risc_mem_dest
- + && GET_CODE (inner_dest) == MEM)
- + /* intel2 - end */
- +
- || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src)))
- return 0;
-
- ***************
- *** 1389,1394 ****
- --- 1444,1468 ----
- return 0;
- }
-
- + /* intel1 */
- + if (in_recombine)
- + {
- + if (i1 && GET_CODE (PATTERN (i1)) == SET
- + && GET_CODE (SET_DEST (PATTERN (i1))) == REG
- + && reg_used_between_p (SET_DEST (PATTERN (i1)), i1, i2))
- + {
- + undo_all ();
- + return 0;
- + }
- + if (i2 && GET_CODE (PATTERN (i2)) == SET
- + && GET_CODE (SET_DEST (PATTERN (i2))) == REG
- + && reg_used_between_p (SET_DEST (PATTERN (i2)), i2, i3))
- + {
- + undo_all ();
- + return 0;
- + }
- + }
- +
- /* Record whether I2DEST is used in I2SRC and similarly for the other
- cases. Knowing this will help in register status updating below. */
- i2dest_in_i2src = reg_overlap_mentioned_p (i2dest, i2src);
- ***************
- *** 2021,2026 ****
- --- 2095,2142 ----
- = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
- }
-
- + /* intel1 , maybe we can rearrange memory so it is recognized */
- + #ifdef REWRITE_ADDRESS
- + if (insn_code_number==-1 && GET_CODE(newpat)==SET && i1==NULL)
- + {
- + rtx copy_of_newpat,try_to_make_good(); /* see loop.c */
- + rtx new_src_copy,new_dest_copy;
- + int dummy;
- + char * storage;
- + storage = (char *) oballoc(0);
- + copy_of_newpat = copy_rtx (newpat);
- + new_src_copy = SET_SRC (copy_of_newpat);
- + try_to_make_good (SET_SRC (copy_of_newpat));
- + try_to_make_good (SET_DEST (copy_of_newpat));
- + if (recog (copy_of_newpat, i3, &dummy) != -1)
- + {
- + int scrat;
- + newpat = copy_of_newpat;
- + insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes, &scrat);
- + }
- + else if (GET_CODE (new_src_copy) != MEM)
- + {
- + new_src_copy = gen_rtx (MEM, GET_MODE( new_src_copy), new_src_copy);
- + try_to_make_good (new_src_copy);
- + SET_SRC (copy_of_newpat) = XEXP (new_src_copy,0);
- + if (recog (copy_of_newpat,i3,&dummy) != -1)
- + {
- + int scrat;
- + newpat = copy_of_newpat;
- + insn_code_number = recog_for_combine (&newpat,i3,&new_i3_notes,&scrat);
- + }
- + else
- + {
- + obfree (storage);
- + }
- + }
- + else
- + {
- + obfree (storage);
- + }
- + }
- + #endif /* REWRITE_ADDRESS */
- +
- /* If it still isn't recognized, fail and change things back the way they
- were. */
- if ((insn_code_number < 0
- ***************
- *** 2031,2036 ****
- --- 2147,2176 ----
- return 0;
- }
-
- + /* intel2 - begin */
- + #ifdef REGISTER_CONSTRAINTS
- + /* check if the combined insn is a legal one */
- + if (in_recombine)
- + {
- + register rtx temp_pat = PATTERN (i3);
- + register int temp_code_number = INSN_CODE (i3);
- +
- + /* change it only for the following check */
- + PATTERN (i3) = newpat;
- + INSN_CODE (i3) = insn_code_number;
- + insn_extract (i3);
- + /* restore the data */
- + PATTERN (i3) = temp_pat;
- + INSN_CODE (i3) = temp_code_number;
- + if (! constrain_operands (insn_code_number, 1))
- + {
- + undo_all();
- + return 0;
- + }
- + }
- + #endif
- + /* intel2 - end */
- +
- /* If we had to change another insn, make sure it is valid also. */
- if (undobuf.other_insn)
- {
- ***************
- *** 4248,4253 ****
- --- 4388,4401 ----
- int other_changed = 0;
- enum machine_mode compare_mode = GET_MODE (dest);
-
- + /* intel1 */
- + #ifdef HAVE_cc0
- + if(SET_DEST (x) == cc0_rtx && compare_mode==VOIDmode)
- + {
- + compare_mode = GET_MODE (SET_SRC (x));
- + }
- + #endif
- +
- if (GET_CODE (src) == COMPARE)
- op0 = XEXP (src, 0), op1 = XEXP (src, 1);
- else
- ***************
- *** 9912,9918 ****
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- {
- if (REG_NOTE_KIND (link) == REG_DEAD
- ! && GET_CODE (XEXP (link, 0)) == REG)
- {
- int regno = REGNO (XEXP (link, 0));
- int endregno
- --- 10060,10072 ----
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- {
- if (REG_NOTE_KIND (link) == REG_DEAD
- ! /* intel2 - begin */
- ! /* if in_recombine we might encounter a REG_DEAD note of memory!
- ! */
- ! && (! in_recombine
- ! || GET_CODE (XEXP (link, 0)) == REG)
- ! /* intel2 - end */
- ! )
- {
- int regno = REGNO (XEXP (link, 0));
- int endregno
- ***************
- *** 10755,10806 ****
-
- if (place == 0)
- {
- ! for (tem = prev_nonnote_insn (i3);
- place == 0 && tem
- && (GET_CODE (tem) == INSN || GET_CODE (tem) == CALL_INSN);
- tem = prev_nonnote_insn (tem))
- ! {
- ! /* If the register is being set at TEM, see if that is all
- ! TEM is doing. If so, delete TEM. Otherwise, make this
- ! into a REG_UNUSED note instead. */
- ! if (reg_set_p (XEXP (note, 0), PATTERN (tem)))
- ! {
- ! rtx set = single_set (tem);
-
- ! /* Verify that it was the set, and not a clobber that
- ! modified the register. */
-
- ! if (set != 0 && ! side_effects_p (SET_SRC (set))
- ! && (rtx_equal_p (XEXP (note, 0), SET_DEST (set))
- ! || (GET_CODE (SET_DEST (set)) == SUBREG
- ! && rtx_equal_p (XEXP (note, 0),
- ! XEXP (SET_DEST (set), 0)))))
- ! {
- ! /* Move the notes and links of TEM elsewhere.
- ! This might delete other dead insns recursively.
- ! First set the pattern to something that won't use
- ! any register. */
- !
- ! PATTERN (tem) = pc_rtx;
- !
- ! distribute_notes (REG_NOTES (tem), tem, tem,
- ! NULL_RTX, NULL_RTX, NULL_RTX);
- ! distribute_links (LOG_LINKS (tem));
- !
- ! PUT_CODE (tem, NOTE);
- ! NOTE_LINE_NUMBER (tem) = NOTE_INSN_DELETED;
- ! NOTE_SOURCE_FILE (tem) = 0;
- ! }
- ! else
- ! {
- ! PUT_REG_NOTE_KIND (note, REG_UNUSED);
- !
- ! /* If there isn't already a REG_UNUSED note, put one
- ! here. */
- ! if (! find_regno_note (tem, REG_UNUSED,
- ! REGNO (XEXP (note, 0))))
- ! place = tem;
- ! break;
- }
- }
- else if (reg_referenced_p (XEXP (note, 0), PATTERN (tem))
- --- 10909,10973 ----
-
- if (place == 0)
- {
- ! for (tem = prev_nonnote_insn (i3);
- place == 0 && tem
- && (GET_CODE (tem) == INSN || GET_CODE (tem) == CALL_INSN);
- tem = prev_nonnote_insn (tem))
- ! {
- ! /* If the register is being set at TEM, see if that is all
- ! TEM is doing. If so, delete TEM. Otherwise, make this
- ! into a REG_UNUSED note instead. */
- ! if (reg_set_p (XEXP (note, 0), PATTERN (tem)))
- ! {
- ! rtx set = single_set (tem);
-
- ! /* Verify that it was the set, and not a clobber that
- ! modified the register. */
-
- ! if (set != 0 && ! side_effects_p (SET_SRC (set))
- ! && (rtx_equal_p (XEXP (note, 0), SET_DEST (set))
- ! || (GET_CODE (SET_DEST (set)) == SUBREG
- ! && rtx_equal_p (XEXP (note, 0),
- ! XEXP (SET_DEST (set), 0)))))
- ! {
- ! /* Move the notes and links of TEM elsewhere.
- ! This might delete other dead insns recursively.
- ! First set the pattern to something that won't use
- ! any register. */
- !
- ! PATTERN (tem) = pc_rtx;
- !
- ! distribute_notes (REG_NOTES (tem), tem, tem,
- ! NULL_RTX, NULL_RTX, NULL_RTX);
- ! distribute_links (LOG_LINKS (tem));
- !
- ! PUT_CODE (tem, NOTE);
- ! NOTE_LINE_NUMBER (tem) = NOTE_INSN_DELETED;
- ! NOTE_SOURCE_FILE (tem) = 0;
- ! }
- ! else
- ! {
- ! /* intel1 making this into reg_unused causes
- ! bug in scheduler since sched will see this
- ! as a reg_dead */
- ! #if 0
- ! PUT_REG_NOTE_KIND (note, REG_UNUSED);
- ! #endif
- !
- ! #if 0
- ! /* If there isn't already a REG_UNUSED note, put one
- ! here. */
- ! if (! find_regno_note (tem, REG_UNUSED,
- ! REGNO (XEXP (note, 0))))
- ! place = tem;
- ! #else
- ! /* If there isn't already a REG_DEAD note, put one
- ! here. */
- ! if (! find_regno_note (tem, REG_DEAD,
- ! REGNO (XEXP (note, 0))))
- ! place = tem;
- ! #endif
- ! break;
- }
- }
- else if (reg_referenced_p (XEXP (note, 0), PATTERN (tem))
- ***************
- *** 10826,10832 ****
- }
- break;
- }
- ! }
-
- /* If we haven't found an insn for the death note and it
- is still a REG_DEAD note, but we have hit a CODE_LABEL,
- --- 10993,10999 ----
- }
- break;
- }
- ! }
-
- /* If we haven't found an insn for the death note and it
- is still a REG_DEAD note, but we have hit a CODE_LABEL,
- ***************
- *** 11100,11103 ****
- --- 11267,13846 ----
- (file,
- "\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n",
- total_attempts, total_merges, total_extras, total_successes);
- + }
- +
- + /* intel1 */
- + /* intel1 - those split insns that remained consecutive should now
- + be combined
- + */
- + void
- + combine_unscheded (f, nregs)
- + rtx f;
- + int nregs;
- + {
- + register rtx insn, next, prev;
- + register int i;
- + register rtx links, nextlinks, note;
- +
- + in_recombine = 1;
- + combine_attempts = 0;
- + combine_merges = 0;
- + combine_extras = 0;
- + combine_successes = 0;
- +
- + combine_max_regno = nregs;
- +
- + reg_last_death = (rtx *) alloca (nregs * sizeof (rtx));
- + reg_last_set = (rtx *) alloca (nregs * sizeof (rtx));
- + reg_last_set_value = (rtx *) alloca (nregs * sizeof (rtx));
- + reg_last_set_table_tick = (int *) alloca (nregs * sizeof (int));
- + reg_last_set_label = (int *) alloca (nregs * sizeof (int));
- + reg_last_set_invalid = (char *) alloca (nregs * sizeof (char));
- +
- + bzero (reg_last_death, nregs * sizeof (rtx));
- + bzero (reg_last_set, nregs * sizeof (rtx));
- + bzero (reg_last_set_value, nregs * sizeof (rtx));
- + bzero (reg_last_set_table_tick, nregs * sizeof (short));
- + bzero (reg_last_set_invalid, nregs * sizeof (char));
- +
- + init_recog_no_volatile ();
- +
- + /* Compute maximum uid value so uid_cuid can be allocated. */
- +
- + for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
- + if (INSN_UID (insn) > i)
- + i = INSN_UID (insn);
- +
- + uid_cuid = (int *) alloca ((i + 1) * sizeof (int));
- +
- + /* Compute the mapping from uids to cuids.
- + Cuids are numbers assigned to insns, like uids,
- + except that cuids increase monotonically through the code.
- +
- + Scan all SETs and see if we can deduce anything about what
- + bits are significant for some registers. */
- +
- + for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
- + {
- + uid_cuid [INSN_UID (insn)] = ++i;
- + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- + note_stores (PATTERN (insn), set_nonzero_bits_and_sign_copies);
- + }
- +
- +
- + label_tick = 1;
- + last_call_cuid = 0;
- + mem_last_set = 0;
- + /* Now scan all the insns in forward order. */
- + for (insn = f; insn; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == CODE_LABEL)
- + label_tick++;
- + if(GET_CODE (insn) == INSN)
- + {
- + /* Try this insn with each insn it links back to. */
- + for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
- + {
- + if(REG_NOTE_KIND (links) != REG_DEP_ANTI
- + /*&& REG_NOTE_KIND (links) != REG_DEP_OUTPUT
- + && */ && (GET_CODE (XEXP (links, 0)) == INSN
- + && next_nonnote_insn (XEXP (links, 0))
- + == ORG_NEXT_INSN (XEXP (links, 0)))
- + && GET_CODE (PATTERN (XEXP (links, 0))) == SET
- + && GET_CODE (SET_DEST (PATTERN (XEXP (links, 0))))
- + == REG
- + && (note
- + = find_regno_note (insn,
- + REG_DEAD,
- + REGNO(SET_DEST (PATTERN (XEXP (links, 0))))))
- + && rtx_equal_p (XEXP (note, 0),
- + SET_DEST (PATTERN (XEXP (links, 0))))
- + /* intel2 - begin */
- + /* combine only insns that were created by memory_simplify.
- + */
- + && (RTX_IS_RISC_P (XEXP (links, 0)))
- + /* intel2 - end */
- + )
- + {
- + /* intel2 - begin */
- + rtx inner_link = LOG_LINKS (XEXP (links, 0));
- + int three_insns = 0;
- +
- + /* Check that we consider the case of three-insns riscified
- + * insn
- + */
- + if (inner_link)
- + {
- + for (; inner_link; inner_link = XEXP (inner_link, 1))
- + {
- + rtx temp_insn = XEXP (inner_link, 0);
- +
- + if (REG_NOTE_KIND (inner_link) != REG_DEP_ANTI
- + /*&& REG_NOTE_KIND (inner_link) != REG_DEP_OUTPUT
- + &&*/ && (GET_CODE (temp_insn) == INSN
- + && next_nonnote_insn (temp_insn) ==
- + ORG_NEXT_INSN (temp_insn))
- + && RTX_IS_RISC_P (temp_insn)
- + && GET_CODE (PATTERN (temp_insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (temp_insn)))
- + == REG
- + && (note
- + = find_regno_note (insn,
- + REG_DEAD,
- + REGNO(SET_DEST (PATTERN (temp_insn)))))
- + && rtx_equal_p (XEXP (note, 0),
- + SET_DEST (PATTERN (temp_insn)))
- + )
- + {
- + try_combine (insn, XEXP (links, 0), temp_insn);
- + three_insns = 1;
- + }
- + }
- + }
- +
- + if (! three_insns)
- + {
- + /* intel2 - end */
- + try_combine (insn, XEXP (links, 0), 0);
- + }
- + }
- + }
- + }
- + if(GET_CODE (insn) == INSN ||
- + GET_CODE (insn) == CALL_INSN ||
- + GET_CODE (insn) == JUMP_INSN)
- + record_dead_and_set_regs (insn);
- + }
- +
- + in_recombine = 0;
- +
- + }
- +
- +
- +
- + /* intel2 - begin */
- +
- + /* we will probably need this - check it and remvoe it if not... */
- +
- + /*#include "hard-reg-set.h"*/
- +
- + /* Set of registers that are free and ready to use at this moment. */
- +
- + HARD_REG_SET free_regs;
- +
- + /* Set of registers that are not recommended for allocating at this moment. */
- +
- + static HARD_REG_SET not_recommended_regs;
- +
- + typedef struct {
- + rtx mem; /* mem rtx, this regno holds */
- + rtx insn_dead; /* insn in which this regno dies */
- + rtx insn_load; /* insn in which this regno is loaded */
- + rtx insn_store; /* insn in which this regno is stored */
- + } MEM_HOLDER;
- +
- + /* Indexed by regno, indicates which register currently, holds a copy of
- + memory and the rtx represents this memory, as well as the insn loaded it,
- + and the insn in which this register was dead. */
- +
- + MEM_HOLDER regno_holds_mem[FIRST_PSEUDO_REGISTER];
- + /* Perform simplification of memory accessed instructions by replacing them
- + with risc-like instructions.
- + FILE is a file to output debugging information on,
- + or zero if such output is not desired. */
- +
- + void
- + memory_simplify (file, f)
- + FILE *file;
- + rtx f;
- + {
- + register int block, j;
- + int regno, limit;
- + int i; /* intel1 */
- + int nregs; /* intel1 */
- + char * fmt; /* intel1 */
- + MEM_HOLDER *mhp;
- + rtx copy_reg = NULL;
- + rtx t_insn;
- +
- + /* record which is the last register used for a spill reload */
- + static int last_load_reg;
- + /* Initialize reg_holds_mem */
- +
- + bzero (regno_holds_mem, sizeof regno_holds_mem);
- +
- + /* since all registers now are hard registers, FIRST_PSEUDO_REGISTER is a
- + valid initialization value */
- +
- + last_load_reg = FIRST_PSEUDO_REGISTER;
- +
- + hard_reg_flow_analysis (f, file, 0 /* no pseudo registers' info. save */ );
- +
- + if (n_basic_blocks <= 0)
- + {
- + return ;
- + }
- + /* To determine which registers are live after any insn, start from
- + the beginning of the basic block and scan insns, noting
- + which registers are set by each insn and which die there. */
- + for (block = 0; block < n_basic_blocks; block++)
- + {
- + register rtx insn;
- + int end_of_block_f;
- +
- + if (file)
- + fprintf (file, "\nblock number: %d:\n", block);
- +
- + last_load_reg = FIRST_PSEUDO_REGISTER;
- + /* since we cannot remove stores before a jump, we clean all the
- + insn_store data */
- +
- + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- + regno_holds_mem[regno].insn_store = 0;
- +
- + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- + /* at the beginning of a block, each non-live hard register is
- + considered free. */
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register int bit = 1 << (regno % REGSET_ELT_BITS);
- + if (basic_block_live_at_start[block][offset] & bit)
- + CLEAR_HARD_REG_BIT (free_regs, regno);
- + else
- + SET_HARD_REG_BIT (free_regs, regno);
- + }
- +
- + /* Traverse the block, an insn by insn, check for memory references,
- + and find whether a risc-like insns instead are valid. If yes,
- + replace the insn by another insn(s). */
- +
- + end_of_block_f = 0; /* signals the end of block reached */
- +
- + for (insn = basic_block_head[block];
- + !end_of_block_f;
- + insn = NEXT_INSN (insn))
- + {
- + rtx note, next, mem_opr = 0;
- + rtx pat = PATTERN (insn);
- + int regno, old_regno;
- + int saved_code;
- +
- + /* try to eliminate as much stores as we can using the free_regs
- + and regno_holds_mem information */
- +
- + if (GET_CODE (insn) == INSN
- + && GET_CODE (pat) == SET
- + && GET_CODE (SET_DEST (pat)) == MEM
- + && GET_CODE (SET_SRC (pat)) == REG
- + && GET_CODE (XEXP (SET_DEST (pat), 0)) != PRE_DEC
- + && GET_CODE (XEXP (SET_DEST (pat), 0)) != PRE_INC
- + && GET_CODE (XEXP (SET_DEST (pat), 0)) != POST_DEC
- + && GET_CODE (XEXP (SET_DEST (pat), 0)) != POST_INC
- + && (i = remove_redundant_store (SET_DEST (pat), block))
- + && file)
- + fprintf (file,
- + "insn %d caused a deletion of a redundant store: %d\n",
- + INSN_UID (insn),
- + i);
- +
- + /* Try to eliminate as much loads as we can using the free_regs
- + and regno_holds_mem information */
- +
- + else if (GET_CODE (insn) == INSN
- + && GET_CODE (pat) == SET
- + && (GET_CODE (SET_DEST (pat)) == REG
- + || GET_CODE (SET_DEST (pat)) == MEM)
- + && (GET_CODE (SET_SRC (pat)) == MEM
- + || (GET_CODE (SET_SRC (pat)) == CONST_INT
- + && flag_risc_const)))
- + {
- + int simple_copy_f = 0;
- + rtx set_src = SET_SRC (pat);
- + rtx set_dest = SET_DEST (pat);
- + enum machine_mode mode = GET_MODE (set_dest);
- +
- + if (GET_CODE (SET_DEST (pat)) == REG)
- + old_regno = REGNO (set_dest);
- + else
- + old_regno = FIRST_PSEUDO_REGISTER;
- +
- + if (old_regno != FIRST_PSEUDO_REGISTER
- + && (next = next_nonnote_insn (insn))
- + && GET_RTX_CLASS (GET_CODE (next)) == 'i'
- + && ((note = find_regno_note (next, REG_DEAD, old_regno))
- + ||
- + (GET_CODE (PATTERN (next)) == SET &&
- + rtx_equal_p (set_dest, SET_DEST (PATTERN (next)))))
- + /* tevid */
- + && (note == NULL
- + || mode == GET_MODE (XEXP (note, 0))))
- + {
- + rtx new_reg = NULL;
- + rtx old_reg = set_dest;
- + int stop_replacement = 0;
- +
- + /* if this load is redundant (i.e. the memory loaded
- + exists in any register, and the register we're loading
- + to will die in the next insn), we can replace loaded
- + register in the next insn with the already loaded register,
- + and delete this insn.
- + */
- + if ((regno = find_regno_holds_mem (set_src, mode))
- + != FIRST_PSEUDO_REGISTER
- + && HARD_REGNO_NREGS (regno, mode) == 1
- + && regno_holds_mem[regno].insn_load
- + #ifdef STACK_REGS
- + && (STACK_REG_P (old_reg)
- + || NON_STACK_REG_P (new_reg = gen_rtx (REG,
- + mode,
- + regno)))
- +
- + #endif
- + && TEST_HARD_REG_BIT (free_regs, regno))
- + {
- + #ifdef STACK_REGS
- + if (!new_reg)
- + new_reg = gen_rtx (REG, mode, regno);
- + #endif
- +
- + /* replace this register in the next insn */
- + init_undo_buf ();
- + saved_code = INSN_CODE (next);
- + subst_in_insn (next,
- + PATTERN (next),
- + old_reg,
- + new_reg,
- + 0,
- + 0);
- + if (note == NULL)
- + { /* Then the dest of next must remain old_reg */
- + SET_DEST (PATTERN (next)) = old_reg;
- + }
- +
- + #ifdef REGISTER_CONSTRAINTS
- +
- + INSN_CODE (next) = recog (PATTERN (next), next, 0);
- + if (INSN_CODE (next) != -1)
- + insn_extract (next);
- +
- + if (INSN_CODE (next) == -1
- + || !constrain_operands (INSN_CODE (next), 1))
- + {
- + /* restore the previous situation */
- + loop_undo_all();
- + INSN_CODE (next) = saved_code;
- + stop_replacement = 1;
- + }
- + #endif
- + if (!stop_replacement)
- + {
- +
- + if (regno != old_regno)
- + {
- + if (note != NULL)
- + {
- + /* The regno in the REG_DEAD note should be
- + also changed */
- +
- + XEXP (note, 0) = new_reg;
- +
- + /* Now, if we replaced a REG_DEAD note, and
- + the new_reg is the destination of the next
- + insn, we should remove this note */
- +
- + if (GET_CODE (SET_DEST (PATTERN (next)))
- + == REG
- + && REGNO (SET_DEST (PATTERN (next)))
- + == regno)
- + remove_death (regno, next);
- + }
- + /* replace the registers in the free_register
- + list */
- +
- + nregs = HARD_REGNO_NREGS (old_regno, mode);
- + for (i = 0; i < nregs; i++)
- + SET_HARD_REG_BIT (free_regs, old_regno + i);
- + nregs = HARD_REGNO_NREGS (regno, mode);
- + for (i = 0; i < nregs; i++)
- + CLEAR_HARD_REG_BIT (free_regs, regno + i);
- + } /* if (regno != old_regno) */
- + else
- + /* regno == old_regno */
- + {
- + /* mark that regno is not free anymore */
- + nregs = HARD_REGNO_NREGS (regno, mode);
- + for (i = 0; i < nregs; i++)
- + CLEAR_HARD_REG_BIT (free_regs, regno + i);
- + }
- +
- + /* now we can delete this insn ... */
- +
- + if (basic_block_head[block] == insn)
- + basic_block_head[block] = NEXT_INSN (insn);
- +
- + mhp = ®no_holds_mem[regno];
- + /* we should reset the RISC flag on the insns
- + added for risc, so that they will not be
- + recombined later */
- +
- +
- + if (mhp -> insn_dead)
- + {
- + t_insn = PREV_INSN (mhp->insn_dead);
- + while (t_insn && RTX_IS_RISC_P (t_insn))
- + {
- + RTX_IS_RISC_P (t_insn) = 0;
- + t_insn = PREV_INSN (t_insn);
- + }
- + remove_death (regno, mhp -> insn_dead);
- + if (! t_insn)
- + /* something went wrong */
- + abort ();
- + }
- +
- + if (file)
- + fprintf (file,
- + "insn %d: deleted - redundant "
- + "load encountered (insn %d)\n",
- + INSN_UID (insn),
- + INSN_UID (mhp -> insn_load));
- +
- + PUT_CODE (insn, NOTE);
- + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (insn) = 0;
- +
- + /* ... and start working on the next insn */
- +
- + continue;
- +
- + } /* if (!stop_replacement) */
- +
- + } /* if ((regno = find_regno_holds_mem (set_src)) !=
- + FIRST_PSEUDO_REGISTER
- + && TEST_HARD_REG_BIT (free_regs, regno)) */
- +
- + else if (regno != FIRST_PSEUDO_REGISTER)
- + /* regno holds the appropriate value but is not free,
- + so we can use its contents to
- + convert this insn to a simple reg to reg copy */
- + {
- + copy_reg = gen_rtx (REG, mode, regno);
- + #ifdef STACK_REGS
- + if (GET_CODE (SET_DEST (pat)) != REG
- + || (STACK_REG_P (SET_DEST (pat))
- + == STACK_REG_P (copy_reg)))
- + #endif
- + {
- + simple_copy_f = 1;
- + }
- + }
- +
- + else if (old_regno == last_load_reg
- + && (regno =
- + find_free_reg (GET_MODE (SET_DEST (pat)))) !=
- + FIRST_PSEUDO_REGISTER
- + && regno != old_regno)
- + {
- + new_reg = gen_rtx (REG, mode, regno);
- +
- + /* replace this insn's register with regno */
- +
- + SET_DEST (pat) = new_reg;
- +
- + /* replace this register in the next insn and its
- + REG_NOTES */
- + init_undo_buf ();
- + saved_code = INSN_CODE (next);
- + subst_in_insn (next,
- + PATTERN (next),
- + old_reg,
- + new_reg,
- + 0,
- + 0);
- + if (note == NULL)
- + { /* Then the dest of next must remain old_reg */
- + SET_DEST (PATTERN (next)) = old_reg;
- + }
- +
- + #ifdef REGISTER_CONSTRAINTS
- + if ((INSN_CODE (next) = recog (PATTERN (next),
- + next,
- + 0)) != -1)
- + insn_extract (next);
- +
- + if (INSN_CODE (next) == -1
- + || !constrain_operands (INSN_CODE (next), 1))
- + {
- + /* restore the previous situation */
- + SET_DEST (pat) = old_reg;
- + loop_undo_all ();
- + INSN_CODE (next) = saved_code;
- + stop_replacement = 1;
- + }
- + #endif
- + if (!stop_replacement)
- + {
- + if (note != NULL)
- + {
- + /* The regno in the REG_DEAD note should be
- + changed */
- +
- + XEXP (note, 0) = new_reg;
- +
- + /* Now, if we replaced a REG_DEAD note, and the
- + new_reg is the destination of the next insn, we
- + should remove this note */
- +
- + if (GET_CODE (SET_DEST (PATTERN (next))) == REG
- + && REGNO (SET_DEST (PATTERN (next))) == regno)
- + remove_death (regno, next);
- + }
- + /* replace the registers in the free_register
- + list */
- +
- + nregs = HARD_REGNO_NREGS (regno, mode);
- + for (i = 0; i < nregs; i++)
- + CLEAR_HARD_REG_BIT (free_regs, regno + i);
- + nregs = HARD_REGNO_NREGS (old_regno, mode);
- + for (i = 0; i < nregs; i++)
- + SET_HARD_REG_BIT (free_regs, old_regno + i);
- +
- + /* replace relevant data in regno_holds_mem */
- + regno_holds_mem[regno].mem = set_src;
- + regno_holds_mem[regno].insn_load = insn;
- + regno_holds_mem[regno].insn_dead = next;
- +
- + if (file)
- + fprintf (file,
- + "insn %d: replacing reload register %d with register %d\n",
- + INSN_UID (insn), old_regno, regno);
- + } /* if (!stop_replacement) */
- +
- + } /* else if (old_regno == last_load_reg
- + && (regno =
- + find_free_reg (GET_MODE (set_dest))) !=
- + FIRST_PSEUDO_REGISTER)
- + */
- +
- + else if (old_regno == last_load_reg
- + && file)
- + fprintf (file,
- + "insn %d: no free register found for reload."
- + "\n",
- + INSN_UID (insn));
- +
- + } /* if ((next = next_nonnote_insn (insn))
- + && GET_RTX_CLASS (GET_CODE (next)) == 'i'
- + && (note = find_regno_note (next, REG_DEAD, old_regno)))
- + */
- +
- + else if ((regno = find_regno_holds_mem (set_src, mode))
- + != FIRST_PSEUDO_REGISTER
- + && HARD_REGNO_NREGS (regno, mode) == 1)
- + {
- + copy_reg = gen_rtx (REG, mode, regno);
- + #ifdef STACK_REGS
- + if (GET_CODE (set_dest) != REG
- + || (STACK_REG_P (set_dest) == STACK_REG_P (copy_reg)))
- + #endif
- + simple_copy_f = 1;
- + }
- +
- + if (simple_copy_f)
- + {
- + MEM_HOLDER *mhp_org;
- + rtx mem;
- +
- + /* we can change this insn to a simple reg copy, instead
- + of a load or store */
- +
- + mem = SET_SRC (pat);
- + if (copy_reg == NULL)
- + {
- + copy_reg = gen_rtx (REG, mode, regno);
- + }
- +
- + saved_code = INSN_CODE (insn);
- + SET_SRC (pat) = copy_reg;
- +
- + #ifdef REGISTER_CONSTRAINTS
- + if ((INSN_CODE (insn) = recog (PATTERN (insn),
- + insn,
- + 0)) != -1)
- + insn_extract (insn);
- +
- + if (INSN_CODE (insn) == -1
- + || !constrain_operands (INSN_CODE (insn), 1))
- + {
- + SET_SRC (pat) = mem;
- + INSN_CODE (insn) = saved_code;
- + }
- + else
- + {
- + #endif
- +
- + /* now we should eliminate the possibility of the risc
- + sequence loaded the memory int regno, to be later
- + recombined */
- +
- + mhp_org = ®no_holds_mem[regno];
- + mhp = ®no_holds_mem[old_regno];
- + if (mhp_org -> insn_load)
- + {
- + /* we should reset the RISC flag on the insns
- + added for risc, so that they will not be
- + recombined later */
- +
- +
- + if (mhp_org -> insn_dead)
- + {
- + t_insn = PREV_INSN (mhp_org->insn_dead);
- + while (t_insn && RTX_IS_RISC_P (t_insn))
- + {
- + RTX_IS_RISC_P (t_insn) = 0;
- + t_insn = PREV_INSN (t_insn);
- + }
- + if (! t_insn)
- + fprintf (stderr,
- + "Not encountered insn_dead\n");
- + remove_death (regno, mhp_org -> insn_dead);
- + }
- + } /* if (mhp_org -> insn_load) */
- +
- + /* we should update old_regno entries in
- + regno_holds_mem array */
- +
- + mhp -> mem = mhp_org -> mem;
- + mhp -> insn_load = insn;
- +
- + if (file)
- + fprintf (file,
- + "insn %d: mem source replaced with reg\n",
- + INSN_UID (insn));
- +
- + #ifdef REGISTER_CONSTRAINTS
- + } /* else of if (INSN_CODE (insn) == -1
- + || !constrain_operands (INSN_CODE (insn), 1))
- + */
- + #endif
- + } /* if (simple_copy_f) */
- +
- + if (GET_CODE (pat) == SET
- + && GET_CODE (SET_DEST (pat)) == REG)
- + last_load_reg = REGNO (SET_DEST (pat));
- +
- + } /* if (GET_CODE (insn) == INSN
- + && GET_CODE (pat) == SET
- + && GET_CODE (SET_DEST (pat)) == REG
- + && GET_CODE (SET_SRC (pat)) == MEM) */
- +
- + /* mark all the original insns (those not created here). Since
- + we use here the same bit as RTX_IS_SPILL_P, we should do this
- + after checking for the spill reload register substitution. */
- + RTX_IS_RISC_P (insn) = 0;
- +
- + end_of_block_f = (insn == basic_block_end[block]);
- + if (!INSN_UID (insn))
- + fatal ("\nMemory simplify: Scanning illegal insn.");
- +
- + if (GET_CODE (insn) == INSN)
- + {
- + register rtx note;
- +
- + if (GET_CODE (pat) == SET)
- + {
- + rtx prev_insn, next_insn;
- + rtx insn_src = SET_SRC (pat);
- + rtx insn_dest = SET_DEST (pat);
- + int mem_opr_is_src = 0;
- +
- + /* indicates which of the two SET_SRC's arguments is a
- + memory reference. 0 - indicates the first one and 1 -
- + the second */
- +
- + int mem_loc;
- +
- + switch (GET_CODE (insn_src))
- + {
- + case CONST_INT:
- + if (flag_risc_const
- + && GET_CODE (insn_dest) == MEM
- + && !push_operand (insn_dest,
- + GET_MODE (insn_dest)))
- + {
- + mem_opr = insn_src;
- + mem_loc = 1;
- + mem_opr_is_src = 1;
- + /* this is a trick to make the code replacing
- + the memory operand in any other insn, valid
- + even here.
- + Note that insn_src now is actually the
- + insn's pattern, and not the SET_SRC of it. */
- + insn_src = pat;
- + }
- + break;
- + case REG:
- + case SYMBOL_REF:
- + /* do nothing, this is a simple copy */
- + break;
- + case MEM:
- + if (GET_CODE (insn_dest) == CC0)
- + /* this insn is not a simple load */
- + {
- + mem_opr = insn_src;
- + mem_loc = 1;
- +
- + mem_opr_is_src = 1;
- + /* this is a trick to make the code replacing
- + the memory operand in any other insn, valid
- + even here.
- + Note that insn_src now is actually the
- + insn's pattern, and not the SET_SRC of it. */
- + insn_src = pat;
- + }
- + break;
- + default:
- + if (GET_CODE (insn_src) == SIGN_EXTRACT
- + || GET_CODE (insn_src) == ZERO_EXTRACT)
- + { /* These cannot be handled properly */
- + break;
- + }
- + fmt = GET_RTX_FORMAT (GET_CODE (insn_src));
- + if (GET_CODE (XEXP (insn_src, 0)) == MEM)
- + {
- + mem_loc = 0;
- + mem_opr = XEXP (insn_src, 0);
- + }
- + else if (GET_RTX_LENGTH (GET_CODE (insn_src)) > 1
- + && fmt[1] == 'e'
- + && GET_CODE (XEXP (insn_src, 1)) == MEM)
- + {
- + mem_loc = 1;
- + mem_opr = XEXP (insn_src, 1);
- + }
- + break;
- + } /* switch (GET_CODE(insn_src)) */
- +
- + if (mem_opr)
- + /* we found a memory operand that we should replace */
- + {
- + int skip_load_f = 0; /* should we skip mem load? */
- + int regno_is_free = 0; /* was it allocated by find_free_reg */
- + int memory_dest_changed
- + = GET_CODE (insn_dest) == MEM
- + && rtx_equal_p (insn_dest, mem_opr);
- + enum machine_mode mode = GET_MODE (mem_opr);
- +
- + if (GET_CODE (mem_opr) == CONST_INT)
- + mode = GET_MODE (insn_dest);
- + if ((regno = find_regno_holds_mem (mem_opr, mode))
- + != FIRST_PSEUDO_REGISTER)
- + {
- + if (HARD_REGNO_NREGS (regno, mode) == 1
- + && TEST_HARD_REG_BIT (free_regs, regno))
- + skip_load_f = 1;
- + else
- + regno = FIRST_PSEUDO_REGISTER;
- + }
- + if (regno == FIRST_PSEUDO_REGISTER
- + #ifdef IS_RISC_MODE
- + && (IS_RISC_MODE (GET_MODE (mem_opr))
- + || GET_CODE (mem_opr) == CONST_INT)
- + #endif
- + )
- + { /* Look forward a few insns to see
- + if this mem_opr will be loaded
- + into a register and if it is then
- + try to use that register for riscifying. */
- + t_insn = next_nonnote_insn (insn);
- + while (t_insn && regno == FIRST_PSEUDO_REGISTER)
- + {
- + if (GET_CODE (t_insn) == CODE_LABEL
- + || GET_CODE (t_insn) == CALL_INSN)
- + {
- + break;
- + }
- + if (GET_CODE (t_insn) == INSN)
- + {
- + register rtx dest;
- +
- + if (GET_CODE (PATTERN (t_insn)) != SET)
- + {
- + break;
- + }
- + dest = SET_DEST (PATTERN (t_insn));
- + if (GET_CODE (dest) == REG
- + && rtx_equal_p (mem_opr,
- + SET_SRC (PATTERN (t_insn))))
- + {
- + regno = REGNO (dest);
- + nregs = HARD_REGNO_NREGS (regno, mode);
- + if (HARD_REGNO_MODE_OK (regno, mode))
- + {
- + for (i = 0; i < nregs; i++)
- + if (! TEST_HARD_REG_BIT (free_regs,
- + regno + i))
- + {
- + regno = FIRST_PSEUDO_REGISTER;
- + break;
- + }
- + }
- + else
- + regno = FIRST_PSEUDO_REGISTER;
- + }
- + else if (GET_CODE (dest) == MEM
- + && ! push_operand (dest,
- + GET_MODE (dest)))
- + /* since there is a write to memory, no use
- + in trying to load something that might be
- + clobbered. */
- + regno = FIRST_PSEUDO_REGISTER;
- + }
- + t_insn = next_nonnote_insn (t_insn);
- + }
- +
- + }
- + if (regno == FIRST_PSEUDO_REGISTER
- + && GET_CODE (insn_dest) == REG
- + #ifdef IS_RISC_MODE
- + && (IS_RISC_MODE (GET_MODE (mem_opr))
- + || GET_CODE (mem_opr) == CONST_INT)
- + #endif
- + )
- + {
- + regno = REGNO (insn_dest);
- + nregs = HARD_REGNO_NREGS (regno, mode);
- +
- + if (HARD_REGNO_MODE_OK (regno, mode))
- + {
- + for (i = 0; i < nregs; i++)
- + if (! TEST_HARD_REG_BIT (free_regs,
- + regno + i))
- + {
- + regno = FIRST_PSEUDO_REGISTER;
- + break;
- + }
- + }
- + else
- + regno = FIRST_PSEUDO_REGISTER;
- + }
- +
- + if (regno == FIRST_PSEUDO_REGISTER
- + #ifdef IS_RISC_MODE
- + && (IS_RISC_MODE (GET_MODE (mem_opr))
- + || GET_CODE (mem_opr) == CONST_INT)
- + #endif
- + )
- + {
- + prev_insn = prev_nonnote_insn (insn);
- + next_insn = next_nonnote_insn (insn);
- +
- + /* update set of not recommended hard registers
- + for find_free_reg () */
- + /* NOTE that we can refer only to integer
- + registers, but now we do it more general. */
- +
- + for (regno = 0;
- + regno < FIRST_PSEUDO_REGISTER;
- + regno++)
- +
- + if ((prev_insn
- + && GET_RTX_CLASS (GET_CODE (prev_insn))
- + == 'i'
- + && (INSN_USES_REGNO (prev_insn, regno)
- + || INSN_SETS_REGNO (prev_insn, regno)))
- + || (next_insn
- + && GET_RTX_CLASS (GET_CODE (next_insn))
- + == 'i'
- + && (INSN_USES_REGNO (next_insn, regno)
- + /* If the destination is MEM we
- + might write the new register
- + contents to the memory as the
- + last insn. This will force us to
- + also consider a write to the
- + allocated register in the next
- + insn. */
- +
- + || (memory_dest_changed
- + && INSN_SETS_REGNO (next_insn,
- + regno)))))
- + SET_HARD_REG_BIT (not_recommended_regs,regno);
- + else
- + CLEAR_HARD_REG_BIT (not_recommended_regs,
- + regno);
- +
- + regno = find_free_reg (mode);
- + regno_is_free = 1;
- + }
- +
- + if (regno != FIRST_PSEUDO_REGISTER)
- + {
- + rtx new_insn, new_reg, link;
- +
- + /* before changing the insn, and adding others, we
- + check the changed insn will be legal. */
- +
- + new_reg = gen_rtx (REG, mode, regno);
- + saved_code = INSN_CODE (insn);
- + if (mem_opr_is_src)
- + {
- + SET_SRC (pat) = new_reg;
- + }
- + else
- + {
- + init_undo_buf ();
- + subst_in_insn (insn, pat, mem_opr, new_reg, 0, 0);
- + }
- +
- + #ifdef REGISTER_CONSTRAINTS
- + /* now check if the insn's O.K. */
- +
- + INSN_CODE (insn) = recog (pat, insn, 0);
- +
- + if (INSN_CODE (insn) != -1)
- + insn_extract (insn);
- +
- + if (INSN_CODE (insn) == -1
- + || ! constrain_operands (INSN_CODE (insn), 1))
- + {
- + if (mem_opr_is_src)
- + {
- + SET_SRC (pat) = mem_opr;
- + }
- + else
- + {
- + loop_undo_all ();
- + }
- + INSN_CODE (insn) = saved_code;
- + }
- + else /* the replacement is valid */
- + {
- + #endif
- + if (! skip_load_f)
- + {
- +
- + if (mode != SImode && regno_is_free
- + && GET_CODE (mem_opr) == CONST_INT)
- + {
- + new_reg = gen_rtx (REG, SImode, regno);
- + }
- + /* load the memory into regno */
- + new_insn
- + = make_insn_raw (gen_rtx (SET,
- + VOIDmode,
- + new_reg,
- + mem_opr));
- +
- + RTX_IS_RISC_P (new_insn) = 1;
- + add_insn_after (new_insn,
- + PREV_INSN (insn));
- +
- + /* record regno as the last register that
- + is used for loading */
- +
- + last_load_reg = regno;
- +
- +
- + /* update new data in regno_holds_mem[] */
- +
- + #if 0
- + mhp = ®no_holds_mem[regno];
- + mhp -> insn_load = new_insn;
- + #endif
- + update_regno_holds_mem(new_insn,
- + PATTERN(new_insn));
- +
- + /* if insn was the first insn in this
- + block this should be updated */
- +
- + if (basic_block_head[block] == insn)
- + basic_block_head[block] = new_insn;
- +
- + if (file)
- + {
- + fprintf (file, "insn %d was added ",
- + INSN_UID (new_insn));
- + fprintf (file, "before insn %d\n",
- + INSN_UID (insn));
- + }
- +
- + /* move the insn's LOG_LINKS to new_insn */
- + LOG_LINKS (new_insn) = LOG_LINKS (insn);
- + LOG_LINKS (insn) = 0;
- +
- + /* move all relevant REG_DEAD notes to
- + new_insn */
- + for (note = REG_NOTES (insn);
- + note;
- + note = XEXP (note, 1))
- + {
- + if (REG_NOTE_KIND (note) == REG_DEAD)
- + {
- + register int regno
- + = REGNO (XEXP (note, 0));
- +
- + if (GET_RTX_LENGTH (
- + GET_CODE (insn_src)) < 2
- + || GET_CODE (XEXP (insn_src,
- + 1 - mem_loc))
- + != REG
- + || REGNO (XEXP (insn_src,
- + 1 - mem_loc))
- + != regno)
- + {
- +
- + /* this note does not refer to
- + the register that will be
- + used from now on within
- + insn, thus we move it to
- + new_insn. */
- +
- + remove_note (insn, note);
- + mhp = ®no_holds_mem[regno];
- + REG_NOTES (new_insn) =
- + gen_rtx (EXPR_LIST,
- + REG_DEAD,
- + XEXP (note, 0),
- + REG_NOTES(new_insn));
- + mhp -> insn_dead = new_insn;
- +
- + SET_HARD_REG_BIT
- + (free_regs,
- + REGNO (XEXP (note, 0)));
- + }
- + } /* if (REG_NOTE_KIND (note) == REG_DEAD) */
- + } /* for (note = REG_NOTES (insn);
- + note;
- + note = XEXP (note, 1)) */
- + } /* if (! skip_load_f) */
- + else
- + /* we use an already loaded register */
- + {
- +
- + /* since we use a load for a possibly
- + previously riscified insn, we should
- + unmark the insns created for that insn,
- + so that recombine will not try to
- + delete its load */
- + mhp = ®no_holds_mem[regno];
- + if (mhp -> insn_dead)
- + {
- + /* we should reset the RISC flag on
- + the insns added for risc, so that
- + they will not be recombined later
- + */
- +
- + t_insn = PREV_INSN (mhp -> insn_dead);
- + while (t_insn && RTX_IS_RISC_P (t_insn))
- + {
- + RTX_IS_RISC_P (t_insn) = 0;
- + t_insn = PREV_INSN (t_insn);
- + }
- + remove_death (regno, mhp->insn_dead);
- + } /* if (mhp -> insn_load) */
- +
- + if (file)
- + {
- + fprintf (file, "insn %d: changed mem ",
- + INSN_UID (insn));
- + fprintf (file, "operand with already "
- + "loaded register %d\n",
- + regno);
- + }
- + }
- +
- + /* in the case the memory operand was also the
- + insn's destination, we should add an insn
- + to store the result, now stored in
- + new_reg. */
- +
- + if (memory_dest_changed)
- + {
- + /* Since memory destination was replaced by
- + a register, its contents is clobbered */
- +
- + #if 0
- + regno_holds_mem[regno].mem = 0;
- + #endif
- + bzero (®no_holds_mem[regno],
- + sizeof (MEM_HOLDER));
- + update_entries (new_reg);
- +
- + new_insn = make_insn_raw (pat);
- +
- + RTX_IS_RISC_P (new_insn) = 1;
- + add_insn_after (new_insn,
- + PREV_INSN (insn));
- +
- + if (skip_load_f
- + && basic_block_head[block] == insn)
- + basic_block_head[block] = new_insn;
- +
- + if (file
- + && ! skip_load_f)
- + {
- + fprintf (file, "insn %d was also ",
- + INSN_UID (new_insn));
- + fprintf (file, "added before insn ");
- + fprintf (file, "%d\n",
- + INSN_UID (insn));
- + }
- + else if (file)
- + {
- + fprintf (file,
- + "insn %d was added before "
- + "insn %d, load was saved\n",
- + INSN_UID (new_insn),
- + INSN_UID (insn));
- + }
- +
- +
- + /* change insn to be just a store insn */
- + PATTERN (insn) = gen_rtx (SET,
- + VOIDmode,
- + mem_opr,
- + new_reg);
- +
- + /* now we might find that a previous
- + store is redundant... */
- + if ((i = remove_redundant_store (mem_opr,
- + block))
- + && file)
- + {
- + fprintf (file,
- + "insn %d: caused deletion of "
- + "a redundant store: %d\n",
- + INSN_UID (insn),
- + i);
- + }
- +
- + /* now we actually changed the insn's
- + code, so we erase the current one and
- + we let next phases (probably sched2) to
- + update this code. */
- +
- + INSN_CODE (insn) = -1;
- +
- + if (! skip_load_f)
- + {
- + /* add the last_new_insn to the new_insn's
- + dependency list */
- +
- + link = rtx_alloc (INSN_LIST);
- + PUT_REG_NOTE_KIND (link, 0);
- + XEXP (link, 0) = PREV_INSN (new_insn);
- + XEXP (link, 1) = LOG_LINKS (new_insn);
- + LOG_LINKS (new_insn) = link;
- + }
- + } /* if (memory_dest_changed) */
- +
- + /* add the new_insn to the insn's dependency
- + list */
- +
- + if (! skip_load_f
- + || memory_dest_changed)
- + {
- + link = rtx_alloc (INSN_LIST);
- + PUT_REG_NOTE_KIND (link, 0);
- + XEXP (link, 0) = new_insn;
- + XEXP (link, 1) = LOG_LINKS (insn);
- + LOG_LINKS (insn) = link;
- + }
- +
- + /* Add a REG_DEAD note to the last insn to
- + indicate that the used register is no
- + longer needed.
- + This is not needed for this phase since we
- + do not remove this register from the free
- + register list (we just mark it to indicate
- + that next allocation of free register, will
- + not return it again, so that dependency
- + between adjacent insns will be as less as
- + possible). */
- +
- + if (GET_CODE (insn_dest) != REG
- + || REGNO (insn_dest) != REGNO (new_reg))
- + {
- + REG_NOTES (insn)
- + = gen_rtx (EXPR_LIST,
- + REG_DEAD,
- + new_reg,
- + REG_NOTES (insn));
- + }
- + #ifdef REGISTER_CONSTRAINTS
- + } /* the replacement is valid */
- + #endif
- + } /* if (regno != FIRST_PSEUDO_REGISTER) */
- + else if (file)
- + {
- + fprintf (file, "insn %d: No suitable free hard",
- + INSN_UID (insn));
- + fprintf (file, " register found for risc\n");
- + }
- + } /* if (mem_opr) */
- + } /* if (GET_CODE (pat) == SET) */
- + } /* if (GET_CODE(insn) == INSN) */
- +
- + if (GET_CODE (insn) == CODE_LABEL)
- + bzero (regno_holds_mem, sizeof regno_holds_mem);
- +
- + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- + {
- +
- + if (GET_CODE (insn) == CALL_INSN)
- + {
- + /* all call clobbered registers are now free */
- +
- + for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
- + if (call_used_regs[j])
- + SET_HARD_REG_BIT (free_regs, j);
- + }
- +
- + update_free_regs (PATTERN (insn));
- +
- + update_regno_holds_mem (insn, PATTERN (insn));
- +
- + /* add each dead register to the free_regs set */
- + /* mark each dead regno in the regno_holds_mem array */
- + for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- + {
- + if ((REG_NOTE_KIND (note) == REG_DEAD
- + || REG_NOTE_KIND (note) == REG_UNUSED)
- + && GET_CODE (XEXP (note, 0)) == REG)
- + {
- + regno = REGNO (XEXP (note, 0));
- + nregs =
- + HARD_REGNO_NREGS (regno, GET_MODE (XEXP (note, 0)));
- +
- + for (i = 0; i < nregs; i++)
- + SET_HARD_REG_BIT (free_regs, regno + i);
- + regno_holds_mem[regno].insn_dead = insn;
- + }
- + }
- + if ((note = find_reg_note (insn, REG_WAS_0, 0)))
- + {
- + rtx set;
- + set = single_set (insn);
- + if (set == NULL
- + || GET_CODE (SET_DEST (set)) == REG)
- + { /* Since reg may have been reused. */
- + remove_note (insn, note);
- + }
- + }
- + } /* if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') */
- + } /* for (insn = basic_block_head[block]; */
- + } /* for (block = 0; block < n_basic_blocks; block++) */
- +
- + /* mark each insn with it's next nonnote insn so that recombine can work */
- + {
- +
- + t_insn = f;
- + while (t_insn)
- + {
- + if (GET_CODE (t_insn) == INSN)
- + ORG_NEXT_INSN (t_insn) = next_nonnote_insn (t_insn);
- + t_insn = NEXT_INSN (t_insn);
- + }
- + }
- + } /* memory_simplify (file, f) */
- +
- +
- + static void
- + dump_free_registers (file)
- + FILE *file;
- + {
- + register int regno;
- +
- + fprintf (file, "Free registers now are: ");
- + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- + if (TEST_HARD_REG_BIT (free_regs, regno))
- + {
- + fprintf (file, " %d", regno);
- + }
- + fprintf (file, "\n");
- + }
- +
- + /* Finds a free register that is able to contain a value of mode MODE.
- + * Returns the number of the hard register (or the first hard register, in
- + * case of multi-register value) found, if such exists, and mark it in the
- + * regs_ever_live array. Otherwise returns FIRST_PSEUDO_REGISTER.
- + */
- +
- + int
- + find_free_reg (mode)
- + enum machine_mode mode;
- + {
- + register int regno;
- +
- + /* record last_reg retunrned. Try next find form this reg on. */
- + static int last_reg;
- +
- + int not_desired; /* is this the "not-desired" regset: i.e. are we going to
- + * take the register from those who are not "safe" within
- + * a function (their values is promised not to be altered).
- + */
- + int second_half; /* is this the second half of the "round-robin" search */
- +
- + #ifdef IS_RISC_MODE
- + if (!IS_RISC_MODE (mode))
- + {
- + return (FIRST_PSEUDO_REGISTER);
- + }
- + #endif
- + /* we handle only DImode SImode, HImode and QImode */
- + switch (mode)
- + {
- + case DImode:
- + case SImode:
- + case HImode:
- + case QImode:
- +
- + /* Try to find the register among those whos value is not "safe"
- + * first.
- + */
- + for (not_desired = 0; not_desired < 2; not_desired++)
- + {
- + int last_reg_scanned = 0;
- +
- + /* implement a "round-robin" algorithm for register scanning.
- + fisrt look from the last_reg and on, and then from 0 to
- + last_reg. */
- +
- + for (regno = (last_reg + 1) % FIRST_PSEUDO_REGISTER;
- + ! last_reg_scanned;
- + regno = (regno + 1) % FIRST_PSEUDO_REGISTER)
- + {
- + register int i, nregs = HARD_REGNO_NREGS (regno, mode);
- + register int found = 1;
- +
- + last_reg_scanned = last_reg == regno;
- + for (i = 0; i < nregs; i++)
- + {
- + if (! not_desired
- + && (! call_used_regs[regno + i]
- + || TEST_HARD_REG_BIT (not_recommended_regs,
- + regno + i)))
- + found = 0;
- + else if (! fixed_regs[regno + i]
- + && TEST_HARD_REG_BIT (free_regs, regno + i)
- + && HARD_REGNO_MODE_OK (regno + i, mode)
- + #ifdef ELIMINABLE_REGS
- + && (! frame_pointer_needed
- + || regno != FRAME_POINTER_REGNUM)
- + #endif
- + /* allow only registers that lived before this
- + phase to take part. This might reduce the number
- + of registers available, but otherwise some
- + problems may occur due to use of a register that
- + need to be pushed at the the function prologue,
- + thus corrupting the calculations of stack slots
- + previously performed at the reload phase. */
- + && (call_used_regs[regno + i]
- + || regs_ever_live[regno + i])
- + )
- + continue;
- + else
- + found = 0;
- + } /* for (i = 0; i < nregs; i++) */
- + if (found)
- + {
- + /* save regno for the next invokation */
- + last_reg = regno + nregs - 1;
- +
- + return (regno);
- + }
- + } /* for (regno = (last_reg + 1) % FIRST_PSEUDO_REG;
- + regno != last_reg;
- + regno = (regno + 1) % FIRST_PSEUDO_REG) */
- + } /* for (not_desired = 0; not_desired < 2; not_desired ++) */
- + break;
- + } /* switch (mode) */
- + return (FIRST_PSEUDO_REGISTER);
- + }
- +
- + /* Updates the free_regs regset according the contents of PAT */
- +
- + void
- + update_free_regs (rtx pat)
- + {
- + register int i, regno, nregs;
- + register j;
- + register char *fmt;
- + register RTX_CODE code = GET_CODE (pat);
- +
- + switch (code)
- + {
- + case SET:
- + case USE:
- + case CLOBBER:
- + if (GET_CODE (SET_DEST (pat)) == REG)
- + {
- + regno = REGNO (SET_DEST (pat));
- + nregs = HARD_REGNO_NREGS (regno,
- + GET_MODE (SET_DEST (pat)));
- +
- + if (GET_CODE (pat) == SET
- + || GET_CODE (pat) == USE)
- + for (i = 0; i < nregs; i++)
- + CLEAR_HARD_REG_BIT (free_regs, regno + i);
- + #if 0
- + else /* GET_CODE (pat) == CLOBBER */
- + for (i = 0; i < nregs; i++)
- + SET_HARD_REG_BIT (free_regs, regno + i);
- + #endif
- + }
- + else if (GET_CODE (SET_DEST (pat)) == SUBREG
- + && GET_CODE (SUBREG_REG (SET_DEST (pat))) == REG)
- + {
- + regno = REGNO (SUBREG_REG (SET_DEST (pat)))
- + + SUBREG_WORD (SET_DEST (pat));
- + nregs = HARD_REGNO_NREGS (regno,
- + GET_MODE (SET_DEST (pat)));
- +
- + if (GET_CODE (pat) == SET
- + || GET_CODE (pat) == USE)
- + for (i = 0; i < nregs; i++)
- + CLEAR_HARD_REG_BIT (free_regs, regno + i);
- + }
- + break;
- + case ADDR_VEC:
- + case CALL:
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + case REG:
- + /* do nothing */
- + return;
- + } /* switch (GET_CODE (pat)) */
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + {
- + if( XEXP (pat, i))
- + update_free_regs (XEXP (pat, i));
- + }
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + update_free_regs (XVECEXP (pat, i, j));
- + }
- + }
- +
- + #if 0
- + /* Returns a hard register regno, if the contents of entry regno in
- + last_reloads array equals to MEM, FIRST_PSEUDO_REGISTER otherwise. */
- +
- + static int
- + find_last_reload (rtx mem)
- + {
- + register int regno;
- +
- + if (GET_CODE (mem) != MEM)
- + abort ();
- +
- + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- + if (rtx_equal_p (LAST_RELOAD (regno), mem))
- + return (regno);
- +
- + return (FIRST_PSEUDO_REGISTER);
- + }
- + #endif
- +
- + /* Returns regno of a free register holding MEM, or FIRST_PSEUDO_REGISTER if
- + not exist such register. */
- +
- + static int
- + find_regno_holds_mem (rtx mem, enum machine_mode mode)
- + {
- + int i, is_const;
- + MEM_HOLDER *mhp;
- +
- + is_const = GET_CODE (mem) == CONST_INT;
- +
- + for (mhp = regno_holds_mem;
- + mhp < regno_holds_mem + FIRST_PSEUDO_REGISTER;
- + mhp++)
- + {
- + if (mhp->mem && GET_CODE (mhp->insn_load) == NOTE)
- + { /* was deleted */
- + mhp->insn_load = NULL;
- + mhp->mem = NULL;
- + mhp->insn_dead = NULL;
- + }
- + if (mhp->insn_store && GET_CODE (mhp->insn_store) == NOTE)
- + { /* was deleted */
- + mhp->insn_store = NULL;
- + }
- + #if 0
- + if ((mhp->insn_load
- + && mhp->mem
- + #endif
- + if ((mhp->mem
- + && GET_CODE (mhp -> mem) == GET_CODE (mem)
- + && (is_const
- + ? rtx_equal_p ( (mhp -> mem), (mem))
- + : rtx_equal_p (XEXP (mhp -> mem, 0), XEXP (mem, 0)))
- + && HARD_REGNO_MODE_OK (mhp - regno_holds_mem, mode)
- + && GET_MODE_SIZE (GET_MODE (SET_DEST (PATTERN (mhp -> insn_load))))
- + >= GET_MODE_SIZE (mode))
- + || (mhp -> mem
- + && mhp -> insn_store
- + && GET_MODE_SIZE (GET_MODE (SET_SRC (PATTERN (mhp -> insn_store))))
- + >= GET_MODE_SIZE (mode)
- + && GET_CODE (SET_DEST ( PATTERN (mhp -> insn_store)))
- + == GET_CODE (mem)
- + && HARD_REGNO_MODE_OK (mhp - regno_holds_mem, mode)
- + && (is_const
- + ? rtx_equal_p (SET_DEST ( PATTERN (mhp -> insn_store)),
- + mem)
- + : rtx_equal_p (XEXP (SET_DEST (PATTERN (mhp -> insn_store)),
- + 0),
- + XEXP (mem, 0)))))
- + return (mhp - regno_holds_mem);
- + }
- + return FIRST_PSEUDO_REGISTER;
- + } /* find_regno_holds_mem (rtx mem) */
- +
- +
- +
- + /* Updates the regno_holds_mem array as required from pat */
- +
- + static void
- + update_regno_holds_mem (rtx insn, rtx pat)
- + {
- + register int i, j, regno, nregs;
- + MEM_HOLDER *mhp;
- + rtx set_src, set_dest;
- + register char *fmt;
- + register RTX_CODE code = GET_CODE (pat);
- +
- + if (GET_CODE (insn) == JUMP_INSN)
- + {
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + regno_holds_mem[i].insn_store = 0;
- + return;
- + }
- +
- + switch (GET_CODE (pat))
- + {
- + case SET:
- + set_src = SET_SRC (pat);
- + set_dest = SET_DEST (pat);
- + if (GET_CODE (set_dest) == REG)
- + {
- + regno = REGNO (set_dest);
- + nregs = HARD_REGNO_NREGS (regno, GET_MODE (set_dest));
- +
- + mhp = ®no_holds_mem[regno];
- + if (nregs == 1
- + && (GET_CODE (set_src) == MEM
- + && !MEM_VOLATILE_P (set_src)
- + && GET_CODE (XEXP (set_src, 0)) != PRE_INC
- + && GET_CODE (XEXP (set_src, 0)) != PRE_DEC
- + && GET_CODE (XEXP (set_src, 0)) != POST_INC
- + && GET_CODE (XEXP (set_src, 0)) != POST_DEC)
- + || GET_CODE (set_src) == CONST_INT)
- + {
- + mhp -> mem = set_src;
- + mhp -> insn_load = insn;
- + mhp -> insn_store = mhp -> insn_dead = 0;
- + }
- + else
- + {
- + for (; mhp < ®no_holds_mem[regno] + nregs; mhp++)
- + {
- + bzero (mhp, sizeof (MEM_HOLDER));
- + }
- + }
- + if (nregs == 1)
- + {
- + /* since we set a register, each mem using this reg is not valid
- + any more */
- +
- + update_entries (set_dest);
- + }
- + else
- + {
- + /* memory holds more than one register. This is a simplification
- + Actually we should zero only those register entries which are
- + relevant for nregs... */
- + bzero (regno_holds_mem, sizeof regno_holds_mem);
- + break;
- + }
- + update_regno_holds_mem (insn, set_src);
- + }
- + else if (GET_CODE (set_dest) == SUBREG)
- + {
- + if (GET_CODE (SUBREG_REG (set_dest)) == REG)
- + {
- + regno = REGNO (SUBREG_REG (set_dest)) + SUBREG_WORD (set_dest);
- + nregs
- + = HARD_REGNO_NREGS (regno, GET_MODE (SUBREG_REG (set_dest)));
- +
- + mhp = ®no_holds_mem[regno];
- + for (; mhp < ®no_holds_mem[regno] + nregs; mhp++)
- + {
- + bzero (mhp, sizeof (MEM_HOLDER));
- + }
- + if (nregs == 1)
- + {
- + update_entries (SUBREG_REG (set_dest));
- + }
- + else
- + {
- + /* memory holds more than one register. This is a simplification.
- + Actually we should zero only those register entries which are
- + relevant for nregs... */
- + bzero (regno_holds_mem, sizeof regno_holds_mem);
- + }
- + update_regno_holds_mem (insn, set_src);
- + return;
- + }
- + else /* subreg of mem */
- + {
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + regno_holds_mem[i].mem = 0;
- + update_regno_holds_mem (insn, XEXP (XEXP (set_dest, 0), 0));
- + update_regno_holds_mem (insn, set_src);
- + return;
- + }
- + }
- + else if (GET_CODE (set_dest) == MEM)
- + {
- + MEM_HOLDER save_mh;
- + int is_push = 0;
- +
- + mhp = 0;
- +
- + if ((GET_CODE (set_src) == REG
- + || GET_CODE (set_src) == CONST_INT)
- + && push_operand (set_dest, Pmode))
- + { /* A push only ruins memory references based on stack_pointer */
- + is_push = 1;
- + }
- + else if (GET_CODE (set_src) == REG
- + /* We might want to add the possibility of SUBREG, isn't it? */
- + && !MEM_VOLATILE_P (set_dest)
- + && GET_CODE (XEXP (set_dest, 0)) != PRE_INC
- + && GET_CODE (XEXP (set_dest, 0)) != PRE_DEC
- + && GET_CODE (XEXP (set_dest, 0)) != POST_INC
- + && GET_CODE (XEXP (set_dest, 0)) != POST_DEC)
- + {
- + register int regno = REGNO (set_src);
- + register int nregs = HARD_REGNO_NREGS (regno,
- + GET_MODE (set_src));
- +
- + if (nregs == 1)
- + {
- + mhp = ®no_holds_mem[regno];
- + save_mh = *mhp;
- + }
- + }
- + else if (GET_CODE (set_src) != REG)
- + update_regno_holds_mem (insn, set_src);
- +
- + if (!is_push)
- + {
- + MEM_HOLDER *p = regno_holds_mem;
- + rtx store_pat;
- +
- + for (; p < regno_holds_mem + FIRST_PSEUDO_REGISTER; p++)
- + {
- + if (p -> mem)
- + {
- + if (GET_CODE (p -> mem) == MEM
- + && true_dependence (set_dest, p -> mem))
- + {
- + p -> mem = 0;
- + }
- + }
- + if (p -> insn_store
- + && (store_pat = PATTERN (p -> insn_store))
- + && GET_CODE (SET_DEST (store_pat)) == MEM
- + && true_dependence (set_dest,
- + SET_DEST (store_pat)))
- + {
- + /* insn_store is not valid any more */
- + p -> insn_store = 0;
- + }
- + }
- + }
- +
- + if (mhp)
- + {
- + /* restore the relevant entry */
- + *mhp = save_mh;
- + mhp -> insn_store = insn;
- +
- + /* if there was no load, we can consider this insn as if it is a
- + load */
- + if (! mhp -> insn_load || GET_CODE (mhp -> insn_load) == NOTE)
- + {
- + mhp -> insn_load = insn;
- + mhp -> mem = set_dest;
- + }
- + }
- + update_regno_holds_mem (insn, XEXP (set_dest, 0));
- + }
- + else
- + {
- + update_regno_holds_mem (insn, set_dest);
- + update_regno_holds_mem (insn, set_src);
- + }
- + return;
- + case CLOBBER:
- + set_dest = SET_DEST (pat);
- + if (GET_CODE (set_dest) == REG)
- + {
- + register int regno = REGNO (set_dest);
- + register int nregs = HARD_REGNO_NREGS (regno,
- + GET_MODE (set_dest));
- +
- + if (nregs == 1)
- + {
- + bzero (®no_holds_mem[regno], sizeof (MEM_HOLDER));
- + update_entries (set_dest);
- + }
- + else
- + /* memory holds more than one register. This is a simplification.
- + Actually we should zero only those register entries which are
- + relevant for nregs... */
- + bzero (regno_holds_mem, sizeof regno_holds_mem);
- + }
- + else if (GET_CODE (set_dest) == SUBREG)
- + {
- + regno = REGNO (SUBREG_REG (set_dest));
- + nregs = HARD_REGNO_NREGS (regno, GET_MODE (XEXP (set_dest, 0)));
- +
- + mhp = ®no_holds_mem[regno];
- + for (; mhp < ®no_holds_mem[regno] + nregs; mhp++)
- + {
- + bzero (mhp, sizeof (MEM_HOLDER));
- + }
- + if (nregs == 1)
- + {
- + update_entries (XEXP (set_dest, 0));
- + }
- + else
- + {
- + /* memory holds more than one register. This is a simplification.
- + Actually we should zero only those register entries which are
- + relevant for nregs... */
- + bzero (regno_holds_mem, sizeof regno_holds_mem);
- + }
- + return;
- + }
- + else if (GET_CODE (set_dest) == MEM)
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + /* the mem field indicates that this regno is no more valid for
- + replacement in loads. Note that this regno might be valid for
- + redundant store, or even replace loads with memory to which
- + this reg was writing in the insn_store, and in such case we
- + would like to reset the risc flags on all insns, from insn_load
- + to insn_dead. This is why we don't reset here insn_load and
- + insn_dead. */
- + if (regno_holds_mem[i].mem
- + && GET_CODE (regno_holds_mem[i].mem) == MEM
- + && true_dependence (set_dest, regno_holds_mem[i].mem))
- + regno_holds_mem[i].mem = 0;
- + }
- + else
- + {
- + fprintf (stderr,
- + "unpredicted case caused reset of regno_holds_mem:\n");
- + fprintf (stderr, "pattern:\n");
- + debug_rtx (pat);
- + fprintf (stderr, "insn:\n");
- + debug_rtx (insn);
- + bzero (regno_holds_mem, sizeof regno_holds_mem);
- + }
- + return;
- + case CALL:
- + /* since we cannot know what writes to memory in the function call,
- + we must not use the information in regno_holds_mem anymore */
- +
- + bzero (regno_holds_mem, sizeof regno_holds_mem);
- + return;
- + case PRE_DEC:
- + case PRE_INC:
- + case POST_DEC:
- + case POST_INC:
- + if (GET_CODE (XEXP (pat, 0)) == REG)
- + {
- + bzero (®no_holds_mem[REGNO (XEXP (pat,0))], sizeof (MEM_HOLDER));
- + update_entries (XEXP (pat, 0));
- + }
- + else
- + {
- + update_regno_holds_mem (insn, XEXP (pat, 0));
- + }
- + return;
- + case MEM:
- + /* there is a use of a memory in this insn, we cannot trust the
- + insn_store data anymore */
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + regno_holds_mem[i].insn_store = 0;
- + if (regno_holds_mem[i].insn_load == NULL)
- + {
- + regno_holds_mem[i].insn_dead = 0;
- + regno_holds_mem[i].mem = NULL;
- + }
- + }
- + update_regno_holds_mem (insn, XEXP (pat, 0));
- + return;
- + case USE:
- + update_regno_holds_mem (insn, SET_DEST (pat));
- + return;
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + case REG:
- + /*case SUBREG:*/
- + /* do nothing */
- + return;
- + } /* switch (GET_CODE (pat)) */
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + {
- + if( XEXP (pat, i))
- + update_regno_holds_mem (insn, XEXP (pat, i));
- + }
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + update_regno_holds_mem (insn, XVECEXP (pat, i, j));
- + }
- + } /* update_regno_holds_mem (rtx pat) */
- +
- +
- +
- +
- + /* Invalidates entries of memory mentioning REG in their memories, and the
- + entry of the appropriate REG */
- +
- + static void
- + update_entries (rtx reg)
- + {
- + register MEM_HOLDER *mhp = regno_holds_mem;
- + register int regno = REGNO (reg);
- +
- + for (; mhp < regno_holds_mem + FIRST_PSEUDO_REGISTER; mhp++)
- + {
- + if (mhp->mem && reg_overlap_mentioned_p (reg, mhp->mem))
- + {
- + if (mhp->insn_store && mhp->insn_store != mhp->insn_load)
- + {
- + mhp -> insn_load = mhp -> insn_store;
- + mhp -> mem = SET_DEST (PATTERN (mhp -> insn_load));
- + mhp -> insn_dead = 0;
- + }
- + else
- + bzero (mhp, sizeof (MEM_HOLDER));
- + }
- + if (mhp -> insn_store && GET_CODE (mhp -> insn_store) == INSN
- + /* insn_store can be deleted by redundant store elimination */
- + && reg_overlap_mentioned_p (reg,
- + SET_DEST (PATTERN (mhp->insn_store))))
- + {
- + if (mhp->insn_load == mhp->insn_store)
- + {
- + bzero (mhp, sizeof (MEM_HOLDER));
- + }
- + else
- + {
- + mhp -> insn_store = 0;
- + }
- + }
- + } /* for (; mhp < regno_holds_mem + FIRST_PSEUDO_REGISTER; mhp++) */
- + } /* update_entries (rtx reg) */
- +
- +
- +
- + /* for each regno found to be non-free (is used or set) from (and including)
- + FIRST, to LAST, clears the appropriate bit in HARD_REG_SET pointed to by
- + FREE. */
- +
- + void
- + find_free_regs_between (free, first, last)
- + HARD_REG_SET *free;
- + rtx first;
- + rtx last;
- +
- + {
- + rtx insn, pat;
- + char *funcname = "find_free_regs_between";
- + register int i;
- +
- +
- + if (! first)
- + abort ();
- + if (! last)
- + abort ();
- +
- + insn = first;
- + while (insn
- + && insn != last)
- + {
- + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- + {
- + if (GET_CODE (insn) == CALL_INSN)
- + {
- + /* we should reset all regs clobbered by a call */
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + if (call_used_regs[i])
- + CLEAR_HARD_REG_BIT (*free, i);
- + }
- + else /* GET_RTX_CLASS (GET_CODE (insn)) != 'i' */
- + {
- + pat = PATTERN (insn);
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + if (INSN_SETS_REGNO (insn, i)
- + || INSN_USES_REGNO (insn, i))
- + CLEAR_HARD_REG_BIT (*free, i);
- + }
- + } /* if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') */
- + insn = NEXT_INSN (insn);
- + }
- + if (insn != last)
- + fprintf (stderr, "%s (): didn't encounterd last!\n", funcname);
- +
- + }
- +
- + /* removes a previous store of MEM if found, and returns INSN_UID of the insn
- + deleted. Otherwise returns 0. */
- + static int
- + remove_redundant_store (rtx mem, int block)
- + {
- + rtx t_insn;
- + int regno;
- +
- + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- + if ((t_insn = regno_holds_mem[regno].insn_store)
- + && GET_CODE (t_insn) == INSN
- + && rtx_equal_p (SET_DEST (PATTERN (t_insn)), mem))
- + {
- + if (basic_block_head[block] == t_insn)
- + basic_block_head[block] = NEXT_INSN (t_insn);
- + PUT_CODE (t_insn, NOTE);
- + NOTE_LINE_NUMBER (t_insn) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (t_insn) = 0;
- +
- + /* if the insn we have just deleted, was preceded with one or two risc
- + additions (i.e. memory_simplify added insns before it), and they are
- + not used for anything else, remove them as well */
- + if (RTX_IS_RISC_P (PREV_INSN (t_insn)))
- + {
- + PUT_CODE (PREV_INSN (t_insn), NOTE);
- + NOTE_LINE_NUMBER (PREV_INSN (t_insn)) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (PREV_INSN (t_insn)) = 0;
- + if (RTX_IS_RISC_P (PREV_INSN (PREV_INSN (t_insn))))
- + {
- + PUT_CODE (PREV_INSN (PREV_INSN (t_insn)), NOTE);
- + NOTE_LINE_NUMBER (PREV_INSN (PREV_INSN (t_insn)))
- + = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (PREV_INSN (PREV_INSN (t_insn))) = 0;
- + }
- + }
- +
- + return INSN_UID (t_insn);
- + }
- + return 0;
- + } /* remove_redundant_store (rtx mem) */
- +
- + /* intel2 - end */
- + /* intel1 */
- +
- + /*
- + Try to eliminate unnecessary reg to reg moves, and also
- + if the destination is a register try to use that register
- + as one of the sources.
- +
- + EXAMPLE:
- +
- + (insn 618 614 616 (set (reg:SI %eax)
- + (mem/s:SI (plus:SI (mult:SI (reg/v:SI %ebx)
- + (const_int 4))
- + (reg:SI %esi)))) -1 (nil)
- + (nil))
- +
- + (insn 616 618 59 (set (reg:SI %esi)
- + (mem:SI (plus:SI (reg:SI %esp)
- + (const_int 36)))) -1 (nil)
- + (nil))
- +
- + (insn:HI 59 616 60 (set (reg:SI %eax)
- + (ior:SI (reg:SI %eax)
- + (mem/s:SI (plus:SI (mult:SI (reg/v:SI %ebx)
- + (const_int 4))
- + (reg:SI %esi))))) 105 {iorsi3} (nil)
- + (nil))
- +
- + (insn 60 59 620 (set (reg:SI %eax)
- + (not:SI (reg:SI %eax))) 130 {one_cmplsi2} (insn_list 59 (nil))
- + (nil))
- +
- + (insn 620 60 61 (set (reg/v:SI %ecx)
- + (reg:SI %eax)) -1 (nil)
- + (expr_list:REG_DEAD (reg:SI %eax)
- + (nil)))
- +
- + WILL BECOME:
- +
- + (insn 618 614 616 (set (reg:SI %ecx)
- + (mem/s:SI (plus:SI (mult:SI (reg/v:SI %ebx)
- + (const_int 4))
- + (reg:SI %esi)))) -1 (nil)
- + (nil))
- +
- + (insn 616 618 59 (set (reg:SI %esi)
- + (mem:SI (plus:SI (reg:SI %esp)
- + (const_int 36)))) -1 (nil)
- + (nil))
- +
- + (insn:HI 59 616 60 (set (reg:SI %ecx)
- + (ior:SI (reg:SI %ecx)
- + (mem/s:SI (plus:SI (mult:SI (reg/v:SI %ebx)
- + (const_int 4))
- + (reg:SI %esi))))) 105 {iorsi3} (nil)
- + (nil))
- +
- + (insn 60 59 620 (set (reg:SI %ecx)
- + (not:SI (reg:SI %ecx))) 130 {one_cmplsi2} (insn_list 59 (nil))
- + (nil))
- +
- + (note 620 60 61 "" NOTE_INSN_DELETED)
- +
- +
- + The trigger for the optimization is:
- +
- + (insn 620 60 61 (set (reg/v:SI %ecx)
- + (reg:SI %eax)) -1 (nil)
- + (expr_list:REG_DEAD (reg:SI %eax)
- + (nil)))
- +
- + */
- + void
- + reg_to_reg_copy_opt (f, file)
- + rtx f;
- + FILE *file;
- + {
- + rtx this_insn, regx, note, src;
- + int regno, success, length, i;
- + char * fmt;
- +
- + if (file)
- + {
- + fprintf (file, "\n\ndoing reg to reg copy opt\n");
- + }
- + hard_reg_flow_analysis (f, NULL, 1);
- + this_insn = f;
- + while (this_insn)
- + {
- + if (GET_CODE (this_insn) == INSN
- + && GET_CODE (PATTERN (this_insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (this_insn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (this_insn))) == REG
- + && REGNO (SET_SRC (PATTERN (this_insn)))
- + != REGNO (SET_DEST (PATTERN (this_insn)))
- + && GET_MODE (SET_SRC (PATTERN (this_insn)))
- + == GET_MODE (SET_DEST (PATTERN (this_insn)))
- + && find_regno_note (this_insn, REG_DEAD,
- + REGNO (SET_SRC (PATTERN (this_insn))))
- + )
- + {
- + success = try_backwards_replace (SET_DEST (PATTERN (this_insn)),
- + SET_SRC (PATTERN (this_insn)),
- + this_insn, 1, file);
- + if (!success)
- + {
- + success = try_forwards_replace (SET_DEST (PATTERN (this_insn)),
- + SET_SRC (PATTERN (this_insn)),
- + this_insn, file);
- + }
- + }
- + else if (GET_CODE (this_insn) == INSN
- + && GET_CODE (PATTERN (this_insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (this_insn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (this_insn))) == SUBREG
- + && REGNO (SET_DEST (PATTERN (this_insn)))
- + != REGNO (SUBREG_REG (SET_SRC (PATTERN (this_insn))))
- + && SUBREG_WORD (SET_SRC (PATTERN (this_insn))) == 0
- + && GET_MODE (SET_SRC (PATTERN (this_insn)))
- + == GET_MODE (SET_DEST (PATTERN (this_insn)))
- + && (note = find_regno_note (this_insn, REG_DEAD,
- + REGNO (SUBREG_REG (SET_SRC (PATTERN (this_insn))))))
- + && rtx_equal_p (XEXP (note, 0),
- + SUBREG_REG (SET_SRC (PATTERN (this_insn))))
- + && HARD_REGNO_NREGS (REGNO (SET_DEST (PATTERN (this_insn))),
- + GET_MODE (SUBREG_REG (SET_SRC (PATTERN (this_insn)))))
- + ==
- + HARD_REGNO_NREGS (REGNO (SET_DEST (PATTERN (this_insn))),
- + GET_MODE (SET_DEST (PATTERN (this_insn))))
- + && HARD_REGNO_NREGS (REGNO (SET_DEST (PATTERN (this_insn))),
- + GET_MODE (SET_DEST (PATTERN (this_insn))))
- + == 1
- + && HARD_REGNO_MODE_OK (REGNO (SET_DEST (PATTERN (this_insn))) ,
- + GET_MODE (SUBREG_REG (SET_SRC (PATTERN (this_insn)))))
- + )
- + {
- + regx = gen_rtx (REG,
- + GET_MODE (SUBREG_REG (SET_SRC (PATTERN (this_insn)))),
- + REGNO (SET_DEST (PATTERN (this_insn))));
- + success
- + = try_backwards_replace (regx,
- + SUBREG_REG (SET_SRC (PATTERN (this_insn))),
- + this_insn, 1, file);
- + if (!success)
- + {
- + success
- + = try_forwards_replace (SET_DEST (PATTERN (this_insn)),
- + SET_SRC (PATTERN (this_insn)),
- + this_insn, file);
- + }
- + }
- + else if (GET_CODE (this_insn) == INSN
- + && GET_CODE (PATTERN (this_insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (this_insn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (this_insn))) != MEM
- + && GET_CODE (SET_SRC (PATTERN (this_insn))) != SUBREG
- + && !reg_overlap_mentioned_p (SET_DEST (PATTERN (this_insn)),
- + SET_SRC (PATTERN (this_insn)))
- + )
- + {
- + src = SET_SRC (PATTERN (this_insn));
- + fmt = GET_RTX_FORMAT (GET_CODE (src));
- + length = GET_RTX_LENGTH (GET_CODE (src));
- + for (i=0; i<length; i++)
- + {
- + if (fmt[i] == 'e'
- + && GET_CODE (XEXP (src, i)) == SUBREG)
- + { /* Makes matters too complex. */
- + return;
- + }
- + }
- + for (i=0; i<length; i++)
- + {
- + if (fmt[i] == 'e'
- + && GET_CODE (XEXP (src, i)) == REG
- + && (note = find_regno_note (this_insn, REG_DEAD,
- + REGNO (XEXP (src, i))))
- + && rtx_equal_p (XEXP (src, i), XEXP (note, 0))
- + )
- + { /* One of the sources dies in this insn -
- + see if the destination register can be used
- + to replace that register. This has a chance
- + of producing better code e.g. reg1 <- reg1 AND reg3
- + produces more efficient code than
- + reg1 <- reg2 AND reg3. */
- + rtx regx, regy;
- + regy = XEXP (src, i);
- + regx = SET_DEST (PATTERN (this_insn));
- + if (reg_overlap_mentioned_p (regx, PATTERN (this_insn)))
- + {
- + break;
- + }
- + if (GET_MODE (regx) != GET_MODE (regy))
- + {
- + if (HARD_REGNO_NREGS (REGNO (regx), GET_MODE (regy)) != 1
- + ||
- + !(HARD_REGNO_MODE_OK (REGNO (regx), GET_MODE (regy))))
- + {
- + continue;
- + }
- + regx = gen_rtx (REG, GET_MODE (regy), REGNO (regx));
- + }
- + if (try_backwards_replace (regx, regy, this_insn, 0, file))
- + {
- + remove_note (this_insn, note);
- + break; /* Since now the dest reg is
- + mentioned in the src. */
- + }
- + }
- + }
- +
- + }
- + this_insn = NEXT_INSN (this_insn);
- + }
- + if (file)
- + {
- + fprintf (file, "\n");
- + }
- + }
- +
- + /*
- + insn is of the form
- + regx <- regy (regy dead)
- + or
- + regx <- SUBREG (regy) (regy dead)
- + or
- + regx <- OP (regy, ...) (regy dead)
- +
- + Search backwards for last previous setting of regy in which the
- + setting of regy can be replaced with regx. If it can then
- + do the replacement and then if delete_flag is set delete insn.
- + */
- +
- + static
- + int
- + try_backwards_replace (regx, regy, insn, delete_flag, file)
- + rtx regx, regy, insn;
- + FILE *file;
- + {
- + rtx this_insn, set_insn, stop_insn;
- + int stop_replacement = 0;
- + int found = 0, insn_code_number, not_yet_recoged;
- +
- +
- + if (file)
- + {
- + fprintf (file, "\ninsn %d reg%d <- reg%d (reg%d dead) (try backwards)\n",
- + INSN_UID(insn), REGNO (regx), REGNO (regy), REGNO(regy));
- + }
- + this_insn = prev_nonnote_insn (insn);
- + /* Find the first previous insn in the block that sets regy and in
- + which regy can be replaced with regx */
- + while (!found && this_insn
- + && !(GET_CODE (this_insn) == CODE_LABEL
- + || GET_CODE (this_insn) == CALL_INSN
- + || GET_CODE (this_insn) == JUMP_INSN))
- + {
- + if (GET_CODE (this_insn) == INSN)
- + {
- + if (GET_CODE (PATTERN (this_insn)) != SET)
- + {
- + return (0);
- + }
- + if (GET_CODE (SET_DEST (PATTERN (this_insn))) == REG)
- + {
- + if (REGNO (regx) == REGNO (SET_DEST (PATTERN (this_insn))))
- + {
- + return (0);
- + }
- + else if (REGNO (regy) == REGNO (SET_DEST (PATTERN (this_insn))))
- + {
- + if (GET_MODE (regy)
- + == GET_MODE (SET_DEST (PATTERN (this_insn))))
- + {
- + #ifdef REGISTER_CONSTRAINTS
- + if (INSN_CODE (this_insn) == -1)
- + {
- + INSN_CODE (this_insn)
- + = recog (PATTERN (this_insn), this_insn, 0);
- + }
- + #endif
- + SET_DEST (PATTERN (this_insn)) = regx;
- + #ifdef REGISTER_CONSTRAINTS
- +
- + if ((insn_code_number
- + = recog (PATTERN (this_insn), this_insn, 0)) < 0
- + || (INSN_CODE (this_insn) != -1
- + && insn_code_number != INSN_CODE (this_insn)))
- + {/* Need to have the same code number since
- + constraints are sometimes more lax than
- + predicates */
- + SET_DEST (PATTERN (this_insn)) = regy;
- + stop_replacement = 1;
- + }
- + else
- + {
- + INSN_CODE (this_insn) = insn_code_number;
- + insn_extract (this_insn);
- + if(!constrain_operands (INSN_CODE (this_insn), 1))
- + {
- + /* restore the previous situation */
- + SET_DEST (PATTERN (this_insn)) = regy;
- + /*INSN_CODE (this_insn)
- + = recog (PATTERN (this_insn), this_insn, 0);*/
- + stop_replacement = 1;
- + }
- + }
- +
- + #endif
- + if (!stop_replacement)
- + {
- + found = 1;
- + set_insn = this_insn;
- + }
- + }
- + else
- + {
- + return (0);
- + }
- + }
- + }
- + else if (reg_overlap_mentioned_p (regx, SET_DEST (PATTERN (this_insn))))
- + {
- + return (0);
- + }
- + if (!found
- + && reg_overlap_mentioned_p (regx, SET_SRC (PATTERN (this_insn))))
- + {
- + return (0);
- + }
- + }
- + if (!found)
- + {
- + stop_replacement = 0;
- + this_insn = prev_nonnote_insn (this_insn);
- + }
- + }
- + if (found)
- + {/* We have found the insn that last sets regy and successfully
- + replaced regx as the dest of that insn.
- + In all insns between set_insn and insn replace regy with regx. */
- + stop_replacement = 0;
- + this_insn = next_nonnote_insn (set_insn);
- + init_undo_buf ();
- + stop_insn = next_nonnote_insn (insn);
- + while (this_insn != stop_insn && !stop_replacement)
- + {
- + #ifdef REGISTER_CONSTRAINTS
- + if (INSN_CODE (this_insn) == -1)
- + {
- + INSN_CODE (this_insn)
- + = recog (PATTERN (this_insn), this_insn, 0);
- + }
- + #endif
- + subst_in_insn (this_insn, PATTERN (this_insn), regy, regx, 0, 0);
- + if (reg_set_p (regy, this_insn)
- + || reg_overlap_mentioned_p (regy, PATTERN (this_insn)))
- + { /* regy was used in some other mode - fail */
- + stop_replacement = 1;
- + }
- + #ifdef REGISTER_CONSTRAINTS
- + if (stop_replacement
- + ||
- + (insn_code_number
- + = recog (PATTERN (this_insn), this_insn, 0)) < 0
- + || (INSN_CODE (this_insn) != -1
- + && insn_code_number != INSN_CODE (this_insn)))
- + {/* Need to have the same code number since constraints
- + are sometimes more lax than predicates */
- + stop_replacement = 1;
- + }
- + else
- + {
- + INSN_CODE (this_insn) = insn_code_number;
- + insn_extract (this_insn);
- + if(!constrain_operands (INSN_CODE (this_insn), 1))
- + {
- + stop_replacement = 1;
- + }
- + }
- + #endif
- + this_insn = next_nonnote_insn ( this_insn);
- + }
- +
- + if (stop_replacement)
- + { /* A replacement was unsuccessful - undo all of the replacements */
- + SET_DEST (PATTERN (set_insn)) = regy;
- + /*INSN_CODE (this_insn)
- + = recog (PATTERN (this_insn), this_insn, 0);*/
- + this_insn = next_nonnote_insn (set_insn);
- + loop_undo_all ();
- + /*while (this_insn != insn)
- + {
- + INSN_CODE (this_insn)
- + = recog (PATTERN (this_insn), this_insn, 0);
- + this_insn = next_nonnote_insn (this_insn);
- + }*/
- + return (0);
- + }
- + else
- + {
- + if (file)
- + {
- + fprintf (file, "replaced dest reg%d of insn %d with reg%d\n",
- + REGNO (regy), INSN_UID (set_insn), REGNO (regx));
- + fprintf (file, " in insns %d through %d replaced reg%d with reg%d\n",
- + INSN_UID (next_nonnote_insn (set_insn)),
- + INSN_UID (insn),
- + REGNO (regy), REGNO (regx));
- + }
- + if (delete_flag)
- + {/* Delete insn */
- + PUT_CODE (insn, NOTE);
- + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (insn) = 0;
- + if (file)
- + {
- + fprintf (file, " deleted insn %d\n", INSN_UID (insn));
- + }
- + }
- + return (1);
- + }
- + }
- + return (0);
- + }
- +
- +
- + /*
- + insn is of the form
- + regx <- regy (regy dead)
- + or
- + regx <- SUBREG (regy) (regy dead)
- +
- + Search forwards for next insn in which the regx is dead.
- + Try to replace all uses of regx with regy in those insns
- + and if successful then delete insn.
- + */
- +
- + static
- + int
- + try_forwards_replace (regx, regy, insn, file)
- + rtx regx, regy, insn;
- + FILE *file;
- + {
- + rtx this_insn, dead_insn, dead_note, stop_insn;
- + int stop_replacement = 0;
- + int found = 0, insn_code_number;
- +
- +
- + if (file)
- + {
- + if (GET_CODE (regy) == REG )
- + fprintf (file, "\ninsn %d reg%d <- reg%d (reg%d dead) (try forwards)\n",
- + INSN_UID(insn), REGNO (regx), REGNO (regy), REGNO(regy));
- + else
- + fprintf (file, "\ninsn %d reg%d <- reg%d (reg%d dead) (try forwards)\n",
- + INSN_UID(insn), REGNO (regx),
- + REGNO (SUBREG_REG (regy)),
- + REGNO (SUBREG_REG (regy)));
- + }
- + this_insn = next_nonnote_insn (insn);
- + /* Find the next insn in the block where regx dies */
- + while (!found && this_insn
- + && !(GET_CODE (this_insn) == CODE_LABEL
- + || GET_CODE (this_insn) == CALL_INSN
- + || GET_CODE (this_insn) == JUMP_INSN))
- + {
- + if (GET_CODE (this_insn) == INSN)
- + {
- + if (GET_CODE (PATTERN (insn)) == USE
- + && reg_overlap_mentioned_p (regx, SET_DEST (PATTERN (insn))))
- + {
- + return (0);
- + }
- + if (reg_set_p (regy, this_insn))
- + {
- + return (0);
- + }
- + else if ((dead_note
- + = find_regno_note (this_insn, REG_DEAD, REGNO (regx)))
- + && rtx_equal_p (XEXP (dead_note, 0), regx))
- + {
- + found = 1;
- + dead_insn = this_insn;
- + }
- + }
- + if (!found)
- + {
- + this_insn = next_nonnote_insn (this_insn);
- + }
- + }
- + if (found)
- + {/* We have found the insn where regx dies. */
- + stop_replacement = 0;
- + this_insn = next_nonnote_insn (insn);
- + init_undo_buf ();
- + stop_insn = next_nonnote_insn (dead_insn);
- + while (this_insn != stop_insn && !stop_replacement)
- + {
- + #ifdef REGISTER_CONSTRAINTS
- + if (INSN_CODE (this_insn) == -1)
- + {
- + INSN_CODE (this_insn)
- + = recog (PATTERN (this_insn), this_insn, 0);
- + }
- + #endif
- + subst_in_insn (this_insn, PATTERN (this_insn), regx, regy, 0, 0);
- + if (reg_set_p (regx, this_insn)
- + || reg_overlap_mentioned_p (regx, PATTERN (this_insn)))
- + { /* regx is used in some other mode - fail. */
- + if (file)
- + {
- + fprintf (file, "fail insn %d reg %d still mentioned\n",
- + INSN_UID (this_insn), REGNO (regx));
- + tdebug_rtx (this_insn, file);
- + }
- + stop_replacement = 1;
- + }
- + #ifdef REGISTER_CONSTRAINTS
- + if (stop_replacement
- + ||
- + (insn_code_number
- + = recog (PATTERN (this_insn), this_insn, 0)) < 0
- + || (INSN_CODE (this_insn) != -1
- + && insn_code_number != INSN_CODE (this_insn)))
- + { /* Need to have the same code number since constraints
- + are sometimes more lax than predicates */
- + if (file)
- + {
- + fprintf (file, "fail insn %d new_recog %d old_recog %d\n",
- + INSN_UID (this_insn), insn_code_number, INSN_CODE (this_insn));
- + }
- + stop_replacement = 1;
- + }
- + else
- + {
- + INSN_CODE (this_insn) = insn_code_number;
- + insn_extract (this_insn);
- + if(!constrain_operands (INSN_CODE (this_insn), 1))
- + {
- + stop_replacement = 1;
- + }
- + }
- + #endif
- + this_insn = next_nonnote_insn ( this_insn);
- + }
- +
- + if (stop_replacement)
- + { /* A replacement was unsuccessful - undo all of the replacements */
- + this_insn = next_nonnote_insn (insn);
- + loop_undo_all ();
- + stop_insn = next_nonnote_insn (dead_insn);
- + /*while (this_insn != stop_insn)
- + {
- + INSN_CODE (this_insn)
- + = recog (PATTERN (this_insn), this_insn, 0);
- + this_insn = next_nonnote_insn (this_insn);
- + }*/
- + return (0);
- + }
- + else
- + { /* Delete insn */
- + PUT_CODE (insn, NOTE);
- + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (insn) = 0;
- + XEXP (dead_note, 0) = regy;
- + if (file)
- + {
- + fprintf (file, " in insns %d through %d replaced reg%d with reg%d\n",
- + INSN_UID (next_nonnote_insn (insn)),
- + INSN_UID (dead_insn),
- + REGNO (regx),
- + GET_CODE (regy) == REG
- + ? REGNO (regy)
- + : REGNO (SUBREG_REG (regy)));
- + fprintf (file, " deleted insn %d\n", INSN_UID (insn));
- + }
- + return (1);
- + }
- + }
- + return (0);
- }
- diff -rNci gcc-2.7.2/config/i386/i386.c gcc-2.7.2p/config/i386/i386.c
- *** gcc-2.7.2/config/i386/i386.c Sun Oct 22 11:13:21 1995
- --- gcc-2.7.2p/config/i386/i386.c Tue Jan 23 09:34:59 1996
- ***************
- *** 1,6 ****
- --- 1,9 ----
- /* Subroutines for insn-output.c for Intel X86.
- Copyright (C) 1988, 1992, 1994, 1995 Free Software Foundation, Inc.
-
- + Pentium cpu support and other enhancements by Tevi Devor Intel Corp.
- + (tevi@iil.intel.com).
- +
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- ***************
- *** 35,40 ****
- --- 38,45 ----
- #include "flags.h"
- #include "function.h"
-
- + /* intel1 Need the EXTRA_CONSTRAINT - changed s to */
- + #if 0
- #ifdef EXTRA_CONSTRAINT
- /* If EXTRA_CONSTRAINT is defined, then the 'S'
- constraint in REG_CLASS_FROM_LETTER will no longer work, and various
- ***************
- *** 43,48 ****
- --- 48,57 ----
- /* The previous line used to be #error, but some compilers barf
- even if the conditional was untrue. */
- #endif
- + #endif
- +
- + /* which cpu are we scheduling for intel1*/
- + enum processor_type x86_cpu;
-
- #define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx))
-
- ***************
- *** 53,88 ****
- char *output_move_const_single ();
- char *output_fp_cc0_set ();
-
- char *hi_reg_name[] = HI_REGISTER_NAMES;
- char *qi_reg_name[] = QI_REGISTER_NAMES;
- char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;
-
- - /* Array of the smallest class containing reg number REGNO, indexed by
- - REGNO. Used by REGNO_REG_CLASS in i386.h. */
- -
- - enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
- - {
- - /* ax, dx, cx, bx */
- - AREG, DREG, CREG, BREG,
- - /* si, di, bp, sp */
- - SIREG, DIREG, INDEX_REGS, GENERAL_REGS,
- - /* FP registers */
- - FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS,
- - FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
- - /* arg pointer */
- - INDEX_REGS
- - };
- -
- - /* Test and compare insns in i386.md store the information needed to
- - generate branch and scc insns here. */
- -
- - struct rtx_def *i386_compare_op0 = NULL_RTX;
- - struct rtx_def *i386_compare_op1 = NULL_RTX;
- - struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
- -
- /* Register allocation order */
- char *i386_reg_alloc_order;
- ! static char regs_allocated[FIRST_PSEUDO_REGISTER];
-
- /* # of registers to use to pass arguments. */
- char *i386_regparm_string; /* # registers to use to pass args */
- --- 62,77 ----
- char *output_move_const_single ();
- char *output_fp_cc0_set ();
-
- + /* intel1 */
- + static int opt_level=0;
- +
- char *hi_reg_name[] = HI_REGISTER_NAMES;
- char *qi_reg_name[] = QI_REGISTER_NAMES;
- char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;
-
- /* Register allocation order */
- char *i386_reg_alloc_order;
- ! /*static char regs_allocated[FIRST_PSEUDO_REGISTER];*/
-
- /* # of registers to use to pass arguments. */
- char *i386_regparm_string; /* # registers to use to pass args */
- ***************
- *** 97,284 ****
- int i386_align_jumps; /* power of two alignment for non-loop jumps */
- int i386_align_funcs; /* power of two alignment for functions */
-
- !
- ! /* Sometimes certain combinations of command options do not make
- ! sense on a particular target machine. You can define a macro
- ! `OVERRIDE_OPTIONS' to take account of this. This macro, if
- ! defined, is executed once just after all the command options have
- ! been parsed.
- !
- ! Don't use this macro to turn on various extra optimizations for
- ! `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
- !
- ! void
- ! override_options ()
- ! {
- ! int ch, i, regno;
- ! char *p;
- ! int def_align;
- !
- ! #ifdef SUBTARGET_OVERRIDE_OPTIONS
- ! SUBTARGET_OVERRIDE_OPTIONS;
- ! #endif
- !
- ! /* Validate registers in register allocation order */
- ! if (i386_reg_alloc_order)
- ! {
- ! for (i = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
- ! {
- ! switch (ch)
- ! {
- ! case 'a': regno = 0; break;
- ! case 'd': regno = 1; break;
- ! case 'c': regno = 2; break;
- ! case 'b': regno = 3; break;
- ! case 'S': regno = 4; break;
- ! case 'D': regno = 5; break;
- ! case 'B': regno = 6; break;
- !
- ! default: fatal ("Register '%c' is unknown", ch);
- ! }
- !
- ! if (regs_allocated[regno])
- ! fatal ("Register '%c' was already specified in the allocation order", ch);
- !
- ! regs_allocated[regno] = 1;
- ! }
- ! }
- !
- ! /* Validate -mregparm= value */
- ! if (i386_regparm_string)
- ! {
- ! i386_regparm = atoi (i386_regparm_string);
- ! if (i386_regparm < 0 || i386_regparm > REGPARM_MAX)
- ! fatal ("-mregparm=%d is not between 0 and %d", i386_regparm, REGPARM_MAX);
- ! }
- !
- ! def_align = (TARGET_386) ? 2 : 4;
- !
- ! /* Validate -malign-loops= value, or provide default */
- ! if (i386_align_loops_string)
- ! {
- ! i386_align_loops = atoi (i386_align_loops_string);
- ! if (i386_align_loops < 0 || i386_align_loops > MAX_CODE_ALIGN)
- ! fatal ("-malign-loops=%d is not between 0 and %d",
- ! i386_align_loops, MAX_CODE_ALIGN);
- ! }
- ! else
- ! i386_align_loops = 2;
- !
- ! /* Validate -malign-jumps= value, or provide default */
- ! if (i386_align_jumps_string)
- ! {
- ! i386_align_jumps = atoi (i386_align_jumps_string);
- ! if (i386_align_jumps < 0 || i386_align_jumps > MAX_CODE_ALIGN)
- ! fatal ("-malign-jumps=%d is not between 0 and %d",
- ! i386_align_jumps, MAX_CODE_ALIGN);
- ! }
- ! else
- ! i386_align_jumps = def_align;
- !
- ! /* Validate -malign-functions= value, or provide default */
- ! if (i386_align_funcs_string)
- ! {
- ! i386_align_funcs = atoi (i386_align_funcs_string);
- ! if (i386_align_funcs < 0 || i386_align_funcs > MAX_CODE_ALIGN)
- ! fatal ("-malign-functions=%d is not between 0 and %d",
- ! i386_align_funcs, MAX_CODE_ALIGN);
- ! }
- ! else
- ! i386_align_funcs = def_align;
- ! }
- !
- ! /* A C statement (sans semicolon) to choose the order in which to
- ! allocate hard registers for pseudo-registers local to a basic
- ! block.
- !
- ! Store the desired register order in the array `reg_alloc_order'.
- ! Element 0 should be the register to allocate first; element 1, the
- ! next register; and so on.
- !
- ! The macro body should not assume anything about the contents of
- ! `reg_alloc_order' before execution of the macro.
- !
- ! On most machines, it is not necessary to define this macro. */
-
- ! void
- ! order_regs_for_local_alloc ()
- {
- ! int i, ch, order, regno;
- !
- ! /* User specified the register allocation order */
- ! if (i386_reg_alloc_order)
- ! {
- ! for (i = order = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
- ! {
- ! switch (ch)
- ! {
- ! case 'a': regno = 0; break;
- ! case 'd': regno = 1; break;
- ! case 'c': regno = 2; break;
- ! case 'b': regno = 3; break;
- ! case 'S': regno = 4; break;
- ! case 'D': regno = 5; break;
- ! case 'B': regno = 6; break;
- ! }
- !
- ! reg_alloc_order[order++] = regno;
- ! }
- !
- ! for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- ! {
- ! if (!regs_allocated[i])
- ! reg_alloc_order[order++] = i;
- ! }
- ! }
- !
- ! /* If users did not specify a register allocation order, favor eax
- ! normally except if DImode variables are used, in which case
- ! favor edx before eax, which seems to cause less spill register
- ! not found messages. */
- ! else
- ! {
- ! rtx insn;
- !
- ! for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- ! reg_alloc_order[i] = i;
- !
- ! if (optimize)
- ! {
- ! int use_dca = FALSE;
- !
- ! for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- ! {
- ! if (GET_CODE (insn) == INSN)
- ! {
- ! rtx set = NULL_RTX;
- ! rtx pattern = PATTERN (insn);
- !
- ! if (GET_CODE (pattern) == SET)
- ! set = pattern;
- !
- ! else if ((GET_CODE (pattern) == PARALLEL
- ! || GET_CODE (pattern) == SEQUENCE)
- ! && GET_CODE (XVECEXP (pattern, 0, 0)) == SET)
- ! set = XVECEXP (pattern, 0, 0);
- !
- ! if (set && GET_MODE (SET_SRC (set)) == DImode)
- ! {
- ! use_dca = TRUE;
- ! break;
- ! }
- ! }
- ! }
-
- ! if (use_dca)
- ! {
- ! reg_alloc_order[0] = 1; /* edx */
- ! reg_alloc_order[1] = 2; /* ecx */
- ! reg_alloc_order[2] = 0; /* eax */
- ! }
- ! }
- ! }
- ! }
-
-
- /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
- attribute for DECL. The attributes in ATTRIBUTES have previously been
- --- 86,112 ----
- int i386_align_jumps; /* power of two alignment for non-loop jumps */
- int i386_align_funcs; /* power of two alignment for functions */
-
- ! /* Array of the smallest class containing reg number REGNO, indexed by
- ! REGNO. Used by REGNO_REG_CLASS in i386.h. */
-
- ! enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
- {
- ! /* ax, dx, cx, bx */
- ! AREG, DREG, CREG, BREG,
- ! /* si, di, bp, sp */
- ! SIREG, DIREG, INDEX_REGS, GENERAL_REGS,
- ! /* FP registers */
- ! FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS,
- ! FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
- ! /* arg pointer */
- ! INDEX_REGS
- ! };
-
- ! /* Test and compare insns in i386.md store the information needed to
- ! generate branch and scc insns here. */
-
- + struct rtx_def *i386_compare_op0, *i386_compare_op1;
- + struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
-
- /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
- attribute for DECL. The attributes in ATTRIBUTES have previously been
- ***************
- *** 635,640 ****
- --- 463,469 ----
- int dies;
- {
- rtx xops[4];
- + int def_align;
- int size = GET_MODE_SIZE (GET_MODE (dest));
-
- xops[0] = AT_SP (Pmode);
- ***************
- *** 681,686 ****
- --- 510,558 ----
- output_asm_insn (AS1 (pop%L0,%0), &dest);
- }
- }
- +
- + /* Validate -mregparm= value */
- + if (i386_regparm_string)
- + {
- + i386_regparm = atoi (i386_regparm_string);
- + if (i386_regparm < 0 || i386_regparm > REGPARM_MAX)
- + fatal ("-mregparm=%d is not between 0 and %d", i386_regparm, REGPARM_MAX);
- + }
- +
- + def_align = (TARGET_386) ? 2 : 4;
- +
- + /* Validate -malign-loops= value, or provide default */
- + if (i386_align_loops_string)
- + {
- + i386_align_loops = atoi (i386_align_loops_string);
- + if (i386_align_loops < 0 || i386_align_loops > MAX_CODE_ALIGN)
- + fatal ("-malign-loops=%d is not between 0 and %d",
- + i386_align_loops, MAX_CODE_ALIGN);
- + }
- + else
- + i386_align_loops = 2;
- +
- + /* Validate -malign-jumps= value, or provide default */
- + if (i386_align_jumps_string)
- + {
- + i386_align_jumps = atoi (i386_align_jumps_string);
- + if (i386_align_jumps < 0 || i386_align_jumps > MAX_CODE_ALIGN)
- + fatal ("-malign-jumps=%d is not between 0 and %d",
- + i386_align_jumps, MAX_CODE_ALIGN);
- + }
- + else
- + i386_align_jumps = def_align;
- +
- + /* Validate -malign-functions= value, or provide default */
- + if (i386_align_funcs_string)
- + {
- + i386_align_funcs = atoi (i386_align_funcs_string);
- + if (i386_align_funcs < 0 || i386_align_funcs > MAX_CODE_ALIGN)
- + fatal ("-malign-functions=%d is not between 0 and %d",
- + i386_align_funcs, MAX_CODE_ALIGN);
- + }
- + else
- + i386_align_funcs = def_align;
- }
-
- char *
- ***************
- *** 735,741 ****
- abort ();
- }
-
- -
- /* Output an insn to add the constant N to the register X. */
-
- static void
- --- 607,612 ----
- ***************
- *** 744,768 ****
- rtx x;
- {
- rtx xops[2];
- ! xops[0] = x;
- !
- ! if (n == -1)
- ! output_asm_insn (AS1 (dec%L0,%0), xops);
- ! else if (n == 1)
- ! output_asm_insn (AS1 (inc%L0,%0), xops);
- ! else if (n < 0)
- {
- ! xops[1] = GEN_INT (-n);
- ! output_asm_insn (AS2 (sub%L0,%1,%0), xops);
- }
- else if (n > 0)
- {
- ! xops[1] = GEN_INT (n);
- ! output_asm_insn (AS2 (add%L0,%1,%0), xops);
- }
- }
-
- -
- /* Output assembler code to perform a doubleword move insn
- with operands OPERANDS. */
-
- --- 615,633 ----
- rtx x;
- {
- rtx xops[2];
- ! xops[1] = x;
- ! if (n < 0)
- {
- ! xops[0] = GEN_INT (-n);
- ! output_asm_insn (AS2 (sub%L0,%0,%1), xops);
- }
- else if (n > 0)
- {
- ! xops[0] = GEN_INT (n);
- ! output_asm_insn (AS2 (add%L0,%0,%1), xops);
- }
- }
-
- /* Output assembler code to perform a doubleword move insn
- with operands OPERANDS. */
-
- ***************
- *** 1081,1342 ****
-
- return "";
- }
- -
-
- ! #define MAX_TMPS 2 /* max temporary registers used */
- !
- ! /* Output the appropriate code to move push memory on the stack */
- !
- ! char *
- ! output_move_pushmem (operands, insn, length, tmp_start, n_operands)
- ! rtx operands[];
- ! rtx insn;
- ! int length;
- ! int tmp_start;
- ! int n_operands;
- {
-
- ! struct {
- ! char *load;
- ! char *push;
- ! rtx xops[2];
- ! } tmp_info[MAX_TMPS];
- !
- ! rtx src = operands[1];
- ! int max_tmps = 0;
- ! int offset = 0;
- ! int stack_p = reg_overlap_mentioned_p (stack_pointer_rtx, src);
- ! int stack_offset = 0;
- ! int i, num_tmps;
- ! rtx xops[1];
-
- ! if (!offsettable_memref_p (src))
- ! fatal_insn ("Source is not offsettable", insn);
-
- ! if ((length & 3) != 0)
- ! fatal_insn ("Pushing non-word aligned size", insn);
-
- ! /* Figure out which temporary registers we have available */
- ! for (i = tmp_start; i < n_operands; i++)
- ! {
- ! if (GET_CODE (operands[i]) == REG)
- ! {
- ! if (reg_overlap_mentioned_p (operands[i], src))
- ! continue;
-
- ! tmp_info[ max_tmps++ ].xops[1] = operands[i];
- ! if (max_tmps == MAX_TMPS)
- ! break;
- ! }
- ! }
-
- ! if (max_tmps == 0)
- ! for (offset = length - 4; offset >= 0; offset -= 4)
- ! {
- ! xops[0] = adj_offsettable_operand (src, offset + stack_offset);
- ! output_asm_insn (AS1(push%L0,%0), xops);
- ! if (stack_p)
- ! stack_offset += 4;
- ! }
-
- ! else
- ! for (offset = length - 4; offset >= 0; )
- ! {
- ! for (num_tmps = 0; num_tmps < max_tmps && offset >= 0; num_tmps++)
- ! {
- ! tmp_info[num_tmps].load = AS2(mov%L0,%0,%1);
- ! tmp_info[num_tmps].push = AS1(push%L0,%1);
- ! tmp_info[num_tmps].xops[0] = adj_offsettable_operand (src, offset + stack_offset);
- ! offset -= 4;
- ! }
-
- ! for (i = 0; i < num_tmps; i++)
- ! output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
-
- ! for (i = 0; i < num_tmps; i++)
- ! output_asm_insn (tmp_info[i].push, tmp_info[i].xops);
-
- ! if (stack_p)
- ! stack_offset += 4*num_tmps;
- ! }
-
- ! return "";
- }
- -
-
- !
- ! /* Output the appropriate code to move data between two memory locations */
- !
- ! char *
- ! output_move_memory (operands, insn, length, tmp_start, n_operands)
- ! rtx operands[];
- ! rtx insn;
- ! int length;
- ! int tmp_start;
- ! int n_operands;
- ! {
- ! struct {
- ! char *load;
- ! char *store;
- ! rtx xops[3];
- ! } tmp_info[MAX_TMPS];
- !
- ! rtx dest = operands[0];
- ! rtx src = operands[1];
- ! rtx qi_tmp = NULL_RTX;
- ! int max_tmps = 0;
- ! int offset = 0;
- ! int i, num_tmps;
- ! rtx xops[3];
- !
- ! if (GET_CODE (dest) == MEM
- ! && GET_CODE (XEXP (dest, 0)) == PRE_INC
- ! && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
- ! return output_move_pushmem (operands, insn, length, tmp_start, n_operands);
- !
- ! if (!offsettable_memref_p (src))
- ! fatal_insn ("Source is not offsettable", insn);
- !
- ! if (!offsettable_memref_p (dest))
- ! fatal_insn ("Destination is not offsettable", insn);
- !
- ! /* Figure out which temporary registers we have available */
- ! for (i = tmp_start; i < n_operands; i++)
- ! {
- ! if (GET_CODE (operands[i]) == REG)
- ! {
- ! if ((length & 1) != 0 && !qi_tmp && QI_REG_P (operands[i]))
- ! qi_tmp = operands[i];
- !
- ! if (reg_overlap_mentioned_p (operands[i], dest))
- ! fatal_insn ("Temporary register overlaps the destination", insn);
- !
- ! if (reg_overlap_mentioned_p (operands[i], src))
- ! fatal_insn ("Temporary register overlaps the source", insn);
- !
- ! tmp_info[ max_tmps++ ].xops[2] = operands[i];
- ! if (max_tmps == MAX_TMPS)
- ! break;
- ! }
- ! }
- !
- ! if (max_tmps == 0)
- ! fatal_insn ("No scratch registers were found to do memory->memory moves", insn);
- !
- ! if ((length & 1) != 0)
- ! {
- ! if (!qi_tmp)
- ! fatal_insn ("No byte register found when moving odd # of bytes.", insn);
- ! }
- !
- ! while (length > 1)
- ! {
- ! for (num_tmps = 0; num_tmps < max_tmps; num_tmps++)
- ! {
- ! if (length >= 4)
- ! {
- ! tmp_info[num_tmps].load = AS2(mov%L0,%1,%2);
- ! tmp_info[num_tmps].store = AS2(mov%L0,%2,%0);
- ! tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset);
- ! tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset);
- ! offset += 4;
- ! length -= 4;
- ! }
- ! else if (length >= 2)
- ! {
- ! tmp_info[num_tmps].load = AS2(mov%W0,%1,%2);
- ! tmp_info[num_tmps].store = AS2(mov%W0,%2,%0);
- ! tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset);
- ! tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset);
- ! offset += 2;
- ! length -= 2;
- ! }
- ! else
- ! break;
- ! }
- !
- ! for (i = 0; i < num_tmps; i++)
- ! output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
- !
- ! for (i = 0; i < num_tmps; i++)
- ! output_asm_insn (tmp_info[i].store, tmp_info[i].xops);
- ! }
- !
- ! if (length == 1)
- ! {
- ! xops[0] = adj_offsettable_operand (dest, offset);
- ! xops[1] = adj_offsettable_operand (src, offset);
- ! xops[2] = qi_tmp;
- ! output_asm_insn (AS2(mov%B0,%1,%2), xops);
- ! output_asm_insn (AS2(mov%B0,%2,%0), xops);
- ! }
- !
- ! return "";
- ! }
- !
- !
- ! int
- ! standard_80387_constant_p (x)
- ! rtx x;
- ! {
- ! #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
- ! REAL_VALUE_TYPE d;
- ! jmp_buf handler;
- ! int is0, is1;
- !
- ! if (setjmp (handler))
- ! return 0;
- !
- ! set_float_handler (handler);
- ! REAL_VALUE_FROM_CONST_DOUBLE (d, x);
- ! is0 = REAL_VALUES_EQUAL (d, dconst0);
- ! is1 = REAL_VALUES_EQUAL (d, dconst1);
- ! set_float_handler (NULL_PTR);
- !
- ! if (is0)
- ! return 1;
- !
- ! if (is1)
- ! return 2;
- !
- ! /* Note that on the 80387, other constants, such as pi,
- ! are much slower to load as standard constants
- ! than to load from doubles in memory! */
- ! #endif
- !
- ! return 0;
- ! }
- !
- ! char *
- ! output_move_const_single (operands)
- ! rtx *operands;
- ! {
- ! if (FP_REG_P (operands[0]))
- ! {
- ! int conval = standard_80387_constant_p (operands[1]);
- !
- ! if (conval == 1)
- ! return "fldz";
- !
- ! if (conval == 2)
- ! return "fld1";
- ! }
- ! if (GET_CODE (operands[1]) == CONST_DOUBLE)
- ! {
- ! REAL_VALUE_TYPE r; long l;
- !
- ! if (GET_MODE (operands[1]) == XFmode)
- ! abort ();
- !
- ! REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- ! REAL_VALUE_TO_TARGET_SINGLE (r, l);
- ! operands[1] = GEN_INT (l);
- ! }
- ! return singlemove_string (operands);
- ! }
- !
- ! /* Returns 1 if OP is either a symbol reference or a sum of a symbol
- ! reference and a constant. */
-
- int
- symbolic_operand (op, mode)
- --- 946,1014 ----
-
- return "";
- }
-
- ! int
- ! standard_80387_constant_p (x)
- ! rtx x;
- {
- + #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
- + REAL_VALUE_TYPE d;
- + jmp_buf handler;
- + int is0, is1;
-
- ! if (setjmp (handler))
- ! return 0;
-
- ! set_float_handler (handler);
- ! REAL_VALUE_FROM_CONST_DOUBLE (d, x);
- ! is0 = REAL_VALUES_EQUAL (d, dconst0);
- ! is1 = REAL_VALUES_EQUAL (d, dconst1);
- ! set_float_handler (NULL_PTR);
-
- ! if (is0)
- ! return 1;
-
- ! if (is1)
- ! return 2;
-
- ! /* Note that on the 80387, other constants, such as pi,
- ! are much slower to load as standard constants
- ! than to load from doubles in memory! */
- ! #endif
-
- ! return 0;
- ! }
-
- ! char *
- ! output_move_const_single (operands)
- ! rtx *operands;
- ! {
- ! if (FP_REG_P (operands[0]))
- ! {
- ! int conval = standard_80387_constant_p (operands[1]);
-
- ! if (conval == 1)
- ! return "fldz";
-
- ! if (conval == 2)
- ! return "fld1";
- ! }
- ! if (GET_CODE (operands[1]) == CONST_DOUBLE)
- ! {
- ! REAL_VALUE_TYPE r; long l;
-
- ! if (GET_MODE (operands[1]) == XFmode)
- ! abort ();
-
- ! REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- ! REAL_VALUE_TO_TARGET_SINGLE (r, l);
- ! operands[1] = GEN_INT (l);
- ! }
- ! return singlemove_string (operands);
- }
-
- ! /* Returns 1 if OP is either a symbol reference or a sum of a symbol
- ! reference and a constant. */
-
- int
- symbolic_operand (op, mode)
- ***************
- *** 1447,1452 ****
- --- 1119,1229 ----
- return 0;
- }
-
- + /* Return a legitimate reference for ORIG (an address) using the
- + register REG. If REG is 0, a new pseudo is generated.
- +
- + There are three types of references that must be handled:
- +
- + 1. Global data references must load the address from the GOT, via
- + the PIC reg. An insn is emitted to do this load, and the reg is
- + returned.
- +
- + 2. Static data references must compute the address as an offset
- + from the GOT, whose base is in the PIC reg. An insn is emitted to
- + compute the address into a reg, and the reg is returned. Static
- + data objects have SYMBOL_REF_FLAG set to differentiate them from
- + global data objects.
- +
- + 3. Constant pool addresses must be handled special. They are
- + considered legitimate addresses, but only if not used with regs.
- + When printed, the output routines know to print the reference with the
- + PIC reg, even though the PIC reg doesn't appear in the RTL.
- +
- + GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
- + reg also appears in the address (except for constant pool references,
- + noted above).
- +
- + "switch" statements also require special handling when generating
- + PIC code. See comments by the `casesi' insn in i386.md for details. */
- +
- + rtx
- + legitimize_pic_address (orig, reg)
- + rtx orig;
- + rtx reg;
- + {
- + rtx addr = orig;
- + rtx new = orig;
- +
- + if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
- + {
- + if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
- + reg = new = orig;
- + else
- + {
- + if (reg == 0)
- + reg = gen_reg_rtx (Pmode);
- +
- + if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
- + new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
- + else
- + new = gen_rtx (MEM, Pmode,
- + gen_rtx (PLUS, Pmode,
- + pic_offset_table_rtx, orig));
- +
- + emit_move_insn (reg, new);
- + }
- + current_function_uses_pic_offset_table = 1;
- + return reg;
- + }
- + else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
- + {
- + rtx base;
- +
- + if (GET_CODE (addr) == CONST)
- + {
- + addr = XEXP (addr, 0);
- + if (GET_CODE (addr) != PLUS)
- + abort ();
- + }
- +
- + if (XEXP (addr, 0) == pic_offset_table_rtx)
- + return orig;
- +
- + if (reg == 0)
- + reg = gen_reg_rtx (Pmode);
- +
- + base = legitimize_pic_address (XEXP (addr, 0), reg);
- + addr = legitimize_pic_address (XEXP (addr, 1),
- + base == reg ? NULL_RTX : reg);
- +
- + if (GET_CODE (addr) == CONST_INT)
- + return plus_constant (base, INTVAL (addr));
- +
- + if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
- + {
- + base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
- + addr = XEXP (addr, 1);
- + }
- + return gen_rtx (PLUS, Pmode, base, addr);
- + }
- + return new;
- + }
- +
- + /* Emit insns to move operands[1] into operands[0]. */
- +
- + void
- + emit_pic_move (operands, mode)
- + rtx *operands;
- + enum machine_mode mode;
- + {
- + rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
- +
- + if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
- + operands[1] = (rtx) force_reg (SImode, operands[1]);
- + else
- + operands[1] = legitimize_pic_address (operands[1], temp);
- + }
- +
- /* This function generates the assembly code for function entry.
- FILE is an stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate. */
- ***************
- *** 1540,1546 ****
- return nregs == 0 || ! frame_pointer_needed;
- }
-
- -
- /* This function generates the assembly code for function exit.
- FILE is an stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to deallocate. */
- --- 1317,1322 ----
- ***************
- *** 1614,1620 ****
- {
- /* On i486, mov & pop is faster than "leave". */
-
- ! if (!TARGET_386)
- {
- xops[0] = frame_pointer_rtx;
- output_asm_insn (AS2 (mov%L2,%0,%2), xops);
- --- 1390,1396 ----
- {
- /* On i486, mov & pop is faster than "leave". */
-
- ! if (TARGET_486)
- {
- xops[0] = frame_pointer_rtx;
- output_asm_insn (AS2 (mov%L2,%0,%2), xops);
- ***************
- *** 1653,3245 ****
- else
- output_asm_insn ("ret", xops);
- }
- -
-
- ! /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- ! that is a valid memory address for an instruction.
- ! The MODE argument is the machine mode for the MEM expression
- ! that wants to use this address.
- !
- ! On x86, legitimate addresses are:
- ! base movl (base),reg
- ! displacement movl disp,reg
- ! base + displacement movl disp(base),reg
- ! index + base movl (base,index),reg
- ! (index + base) + displacement movl disp(base,index),reg
- ! index*scale movl (,index,scale),reg
- ! index*scale + disp movl disp(,index,scale),reg
- ! index*scale + base movl (base,index,scale),reg
- ! (index*scale + base) + disp movl disp(base,index,scale),reg
- !
- ! In each case, scale can be 1, 2, 4, 8. */
- !
- ! /* This is exactly the same as print_operand_addr, except that
- ! it recognizes addresses instead of printing them.
- !
- ! It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should
- ! convert common non-canonical forms to canonical form so that they will
- ! be recognized. */
- !
- ! #define ADDR_INVALID(msg,insn) \
- ! do { \
- ! if (TARGET_DEBUG_ADDR) \
- ! { \
- ! fprintf (stderr, msg); \
- ! debug_rtx (insn); \
- ! } \
- ! } while (0)
-
- ! int
- ! legitimate_address_p (mode, addr, strict)
- ! enum machine_mode mode;
- ! register rtx addr;
- ! int strict;
- {
- ! rtx base = NULL_RTX;
- ! rtx indx = NULL_RTX;
- ! rtx scale = NULL_RTX;
- ! rtx disp = NULL_RTX;
- !
- ! if (TARGET_DEBUG_ADDR)
- ! {
- ! fprintf (stderr,
- ! "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
- ! GET_MODE_NAME (mode), strict);
- !
- ! debug_rtx (addr);
- ! }
- !
- ! if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
- ! base = addr; /* base reg */
-
- ! else if (GET_CODE (addr) == PLUS)
- {
- ! rtx op0 = XEXP (addr, 0);
- ! rtx op1 = XEXP (addr, 1);
- ! enum rtx_code code0 = GET_CODE (op0);
- ! enum rtx_code code1 = GET_CODE (op1);
-
- ! if (code0 == REG || code0 == SUBREG)
- {
- ! if (code1 == REG || code1 == SUBREG)
- ! {
- ! indx = op0; /* index + base */
- ! base = op1;
- ! }
- !
- ! else
- ! {
- ! base = op0; /* base + displacement */
- ! disp = op1;
- ! }
- ! }
- !
- ! else if (code0 == MULT)
- ! {
- ! indx = XEXP (op0, 0);
- ! scale = XEXP (op0, 1);
- !
- ! if (code1 == REG || code1 == SUBREG)
- ! base = op1; /* index*scale + base */
- !
- ! else
- ! disp = op1; /* index*scale + disp */
- ! }
- !
- ! else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
- ! {
- ! indx = XEXP (XEXP (op0, 0), 0); /* index*scale + base + disp */
- ! scale = XEXP (XEXP (op0, 0), 1);
- ! base = XEXP (op0, 1);
- ! disp = op1;
- ! }
- !
- ! else if (code0 == PLUS)
- ! {
- ! indx = XEXP (op0, 0); /* index + base + disp */
- ! base = XEXP (op0, 1);
- ! disp = op1;
- }
-
- else
- ! {
- ! ADDR_INVALID ("PLUS subcode is not valid.\n", op0);
- ! return FALSE;
- ! }
- ! }
-
- ! else if (GET_CODE (addr) == MULT)
- ! {
- ! indx = XEXP (addr, 0); /* index*scale */
- ! scale = XEXP (addr, 1);
- ! }
-
- ! else
- ! disp = addr; /* displacement */
-
- ! /* Allow arg pointer and stack pointer as index if there is not scaling */
- ! if (base && indx && !scale
- ! && (indx == arg_pointer_rtx || indx == stack_pointer_rtx))
- ! {
- ! rtx tmp = base;
- ! base = indx;
- ! indx = tmp;
- ! }
-
- ! /* Validate base register */
- ! /* Don't allow SUBREG's here, it can lead to spill failures when the base
- ! is one word out of a two word structure, which is represented internally
- ! as a DImode int. */
- ! if (base)
- ! {
- ! if (GET_CODE (base) != REG)
- ! {
- ! ADDR_INVALID ("Base is not a register.\n", base);
- ! return FALSE;
- ! }
-
- ! if ((strict && !REG_OK_FOR_BASE_STRICT_P (base))
- ! || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base)))
- {
- ! ADDR_INVALID ("Base is not valid.\n", base);
- ! return FALSE;
- }
- ! }
-
- ! /* Validate index register */
- ! /* Don't allow SUBREG's here, it can lead to spill failures when the index
- ! is one word out of a two word structure, which is represented internally
- ! as a DImode int. */
- ! if (indx)
- ! {
- ! if (GET_CODE (indx) != REG)
- {
- ! ADDR_INVALID ("Index is not a register.\n", indx);
- ! return FALSE;
- }
- !
- ! if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx))
- ! || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx)))
- {
- ! ADDR_INVALID ("Index is not valid.\n", indx);
- ! return FALSE;
- }
- ! }
- ! else if (scale)
- ! abort (); /* scale w/o index invalid */
- !
- ! /* Validate scale factor */
- ! if (scale)
- ! {
- ! HOST_WIDE_INT value;
-
- ! if (GET_CODE (scale) != CONST_INT)
- ! {
- ! ADDR_INVALID ("Scale is not valid.\n", scale);
- ! return FALSE;
- ! }
-
- ! value = INTVAL (scale);
- ! if (value != 1 && value != 2 && value != 4 && value != 8)
- ! {
- ! ADDR_INVALID ("Scale is not a good multiplier.\n", scale);
- ! return FALSE;
- ! }
- }
-
- ! /* Validate displacement */
- ! if (disp)
- {
- ! if (!CONSTANT_ADDRESS_P (disp))
- {
- ! ADDR_INVALID ("Displacement is not valid.\n", disp);
- ! return FALSE;
- ! }
-
- ! if (GET_CODE (disp) == CONST_DOUBLE)
- ! {
- ! ADDR_INVALID ("Displacement is a const_double.\n", disp);
- ! return FALSE;
- ! }
-
- ! if (flag_pic && SYMBOLIC_CONST (disp) && base != pic_offset_table_rtx
- ! && (indx != pic_offset_table_rtx || scale != NULL_RTX))
- ! {
- ! ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
- ! return FALSE;
- ! }
-
- ! if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
- ! && (base != NULL_RTX || indx != NULL_RTX))
- ! {
- ! ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp);
- ! return FALSE;
- ! }
- ! }
-
- ! if (TARGET_DEBUG_ADDR)
- ! fprintf (stderr, "Address is valid.\n");
-
- ! /* Everything looks valid, return true */
- ! return TRUE;
- ! }
-
- !
- ! /* Return a legitimate reference for ORIG (an address) using the
- ! register REG. If REG is 0, a new pseudo is generated.
-
- ! There are three types of references that must be handled:
-
- ! 1. Global data references must load the address from the GOT, via
- ! the PIC reg. An insn is emitted to do this load, and the reg is
- ! returned.
-
- ! 2. Static data references must compute the address as an offset
- ! from the GOT, whose base is in the PIC reg. An insn is emitted to
- ! compute the address into a reg, and the reg is returned. Static
- ! data objects have SYMBOL_REF_FLAG set to differentiate them from
- ! global data objects.
-
- ! 3. Constant pool addresses must be handled special. They are
- ! considered legitimate addresses, but only if not used with regs.
- ! When printed, the output routines know to print the reference with the
- ! PIC reg, even though the PIC reg doesn't appear in the RTL.
-
- ! GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
- ! reg also appears in the address (except for constant pool references,
- ! noted above).
-
- ! "switch" statements also require special handling when generating
- ! PIC code. See comments by the `casesi' insn in i386.md for details. */
-
- ! rtx
- ! legitimize_pic_address (orig, reg)
- ! rtx orig;
- ! rtx reg;
- ! {
- ! rtx addr = orig;
- ! rtx new = orig;
-
- ! if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
- ! {
- ! if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
- ! reg = new = orig;
- ! else
- ! {
- ! if (reg == 0)
- ! reg = gen_reg_rtx (Pmode);
-
- ! if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
- ! || GET_CODE (addr) == LABEL_REF)
- ! new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
- ! else
- ! new = gen_rtx (MEM, Pmode,
- ! gen_rtx (PLUS, Pmode,
- ! pic_offset_table_rtx, orig));
-
- ! emit_move_insn (reg, new);
- ! }
- ! current_function_uses_pic_offset_table = 1;
- ! return reg;
- ! }
- ! else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
- ! {
- ! rtx base;
-
- ! if (GET_CODE (addr) == CONST)
- ! {
- ! addr = XEXP (addr, 0);
- ! if (GET_CODE (addr) != PLUS)
- ! abort ();
- ! }
-
- ! if (XEXP (addr, 0) == pic_offset_table_rtx)
- ! return orig;
-
- ! if (reg == 0)
- ! reg = gen_reg_rtx (Pmode);
- !
- ! base = legitimize_pic_address (XEXP (addr, 0), reg);
- ! addr = legitimize_pic_address (XEXP (addr, 1),
- ! base == reg ? NULL_RTX : reg);
- !
- ! if (GET_CODE (addr) == CONST_INT)
- ! return plus_constant (base, INTVAL (addr));
- !
- ! if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
- {
- ! base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
- ! addr = XEXP (addr, 1);
- }
- ! return gen_rtx (PLUS, Pmode, base, addr);
- }
- - return new;
- }
-
- !
- ! /* Emit insns to move operands[1] into operands[0]. */
-
- void
- ! emit_pic_move (operands, mode)
- ! rtx *operands;
- ! enum machine_mode mode;
- ! {
- ! rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
- !
- ! if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
- ! operands[1] = (rtx) force_reg (SImode, operands[1]);
- ! else
- ! operands[1] = legitimize_pic_address (operands[1], temp);
- ! }
- !
- !
- ! /* Try machine-dependent ways of modifying an illegitimate address
- ! to be legitimate. If we find one, return the new, valid address.
- ! This macro is used in only one place: `memory_address' in explow.c.
- !
- ! OLDX is the address as it was before break_out_memory_refs was called.
- ! In some cases it is useful to look at this to decide what needs to be done.
- !
- ! MODE and WIN are passed so that this macro can use
- ! GO_IF_LEGITIMATE_ADDRESS.
- !
- ! It is always safe for this macro to do nothing. It exists to recognize
- ! opportunities to optimize the output.
- !
- ! For the 80386, we handle X+REG by loading X into a register R and
- ! using R+REG. R will go in a general reg and indexing will be used.
- ! However, if REG is a broken-out memory address or multiplication,
- ! nothing needs to be done because REG can certainly go in a general reg.
- !
- ! When -fpic is used, special handling is needed for symbolic references.
- ! See comments by legitimize_pic_address in i386.c for details. */
- !
- ! rtx
- ! legitimize_address (x, oldx, mode)
- ! register rtx x;
- ! register rtx oldx;
- ! enum machine_mode mode;
- {
- ! int changed = 0;
- ! unsigned log;
- !
- ! if (TARGET_DEBUG_ADDR)
- ! {
- ! fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode));
- ! debug_rtx (x);
- ! }
- !
- ! if (flag_pic && SYMBOLIC_CONST (x))
- ! return legitimize_pic_address (x, 0);
-
- ! /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
- ! if (GET_CODE (x) == ASHIFT
- ! && GET_CODE (XEXP (x, 1)) == CONST_INT
- ! && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
- {
- ! changed = 1;
- ! x = gen_rtx (MULT, Pmode,
- ! force_reg (Pmode, XEXP (x, 0)),
- ! GEN_INT (1 << log));
- ! }
-
- ! if (GET_CODE (x) == PLUS)
- ! {
- ! /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
- ! if (GET_CODE (XEXP (x, 0)) == ASHIFT
- ! && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- ! && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)
- {
- ! changed = 1;
- ! XEXP (x, 0) = gen_rtx (MULT, Pmode,
- ! force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
- ! GEN_INT (1 << log));
- }
- !
- ! if (GET_CODE (XEXP (x, 1)) == ASHIFT
- ! && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
- ! && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)
- {
- ! changed = 1;
- ! XEXP (x, 1) = gen_rtx (MULT, Pmode,
- ! force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
- ! GEN_INT (1 << log));
- }
- !
- ! /* Put multiply first if it isn't already */
- ! if (GET_CODE (XEXP (x, 1)) == MULT)
- {
- ! rtx tmp = XEXP (x, 0);
- ! XEXP (x, 0) = XEXP (x, 1);
- ! XEXP (x, 1) = tmp;
- ! changed = 1;
- }
- !
- ! /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
- ! into (plus (plus (mult (reg) (const)) (reg)) (const)). This can be
- ! created by virtual register instantiation, register elimination, and
- ! similar optimizations. */
- ! if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
- {
- ! changed = 1;
- ! x = gen_rtx (PLUS, Pmode,
- ! gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),
- ! XEXP (XEXP (x, 1), 1));
- }
-
- ! /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
- ! into (plus (plus (mult (reg) (const)) (reg)) (const)). */
- ! else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
- ! && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
- ! && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
- ! && CONSTANT_P (XEXP (x, 1)))
- {
- ! rtx constant, other;
-
- ! if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- ! {
- ! constant = XEXP (x, 1);
- ! other = XEXP (XEXP (XEXP (x, 0), 1), 1);
- ! }
- ! else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
- {
- ! constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
- ! other = XEXP (x, 1);
- }
- - else
- - constant = 0;
-
- ! if (constant)
- {
- ! changed = 1;
- ! x = gen_rtx (PLUS, Pmode,
- ! gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),
- ! XEXP (XEXP (XEXP (x, 0), 1), 0)),
- ! plus_constant (other, INTVAL (constant)));
- }
- - }
- -
- - if (changed && legitimate_address_p (mode, x, FALSE))
- - return x;
-
- ! if (GET_CODE (XEXP (x, 0)) == MULT)
- ! {
- ! changed = 1;
- ! XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
- ! }
-
- ! if (GET_CODE (XEXP (x, 1)) == MULT)
- ! {
- ! changed = 1;
- ! XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
- ! }
-
- ! if (changed
- ! && GET_CODE (XEXP (x, 1)) == REG
- ! && GET_CODE (XEXP (x, 0)) == REG)
- ! return x;
-
- ! if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
- ! {
- ! changed = 1;
- ! x = legitimize_pic_address (x, 0);
- }
-
- ! if (changed && legitimate_address_p (mode, x, FALSE))
- ! return x;
- !
- ! if (GET_CODE (XEXP (x, 0)) == REG)
- ! {
- ! register rtx temp = gen_reg_rtx (Pmode);
- ! register rtx val = force_operand (XEXP (x, 1), temp);
- ! if (val != temp)
- ! emit_move_insn (temp, val);
- !
- ! XEXP (x, 1) = temp;
- ! return x;
- ! }
-
- ! else if (GET_CODE (XEXP (x, 1)) == REG)
- {
- ! register rtx temp = gen_reg_rtx (Pmode);
- ! register rtx val = force_operand (XEXP (x, 0), temp);
- ! if (val != temp)
- ! emit_move_insn (temp, val);
- !
- ! XEXP (x, 0) = temp;
- ! return x;
- }
- }
- -
- - return x;
- }
- -
-
- ! /* Print an integer constant expression in assembler syntax. Addition
- ! and subtraction are the only arithmetic that may appear in these
- ! expressions. FILE is the stdio stream to write to, X is the rtx, and
- ! CODE is the operand print code from the output string. */
-
- ! static void
- ! output_pic_addr_const (file, x, code)
- ! FILE *file;
- ! rtx x;
- ! int code;
- ! {
- ! char buf[256];
-
- ! switch (GET_CODE (x))
- {
- ! case PC:
- ! if (flag_pic)
- ! putc ('.', file);
- ! else
- ! abort ();
- ! break;
- !
- ! case SYMBOL_REF:
- ! case LABEL_REF:
- ! if (GET_CODE (x) == SYMBOL_REF)
- ! assemble_name (file, XSTR (x, 0));
- ! else
- {
- ! ASM_GENERATE_INTERNAL_LABEL (buf, "L",
- ! CODE_LABEL_NUMBER (XEXP (x, 0)));
- ! assemble_name (asm_out_file, buf);
- }
-
- ! if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
- ! fprintf (file, "@GOTOFF(%%ebx)");
- ! else if (code == 'P')
- ! fprintf (file, "@PLT");
- ! else if (GET_CODE (x) == LABEL_REF)
- ! fprintf (file, "@GOTOFF");
- ! else if (! SYMBOL_REF_FLAG (x))
- ! fprintf (file, "@GOT");
- ! else
- ! fprintf (file, "@GOTOFF");
- !
- ! break;
- !
- ! case CODE_LABEL:
- ! ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
- ! assemble_name (asm_out_file, buf);
- ! break;
- !
- ! case CONST_INT:
- ! fprintf (file, "%d", INTVAL (x));
- ! break;
- !
- ! case CONST:
- ! /* This used to output parentheses around the expression,
- ! but that does not work on the 386 (either ATT or BSD assembler). */
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- ! break;
-
- ! case CONST_DOUBLE:
- ! if (GET_MODE (x) == VOIDmode)
- {
- ! /* We can use %d if the number is <32 bits and positive. */
- ! if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
- ! fprintf (file, "0x%x%08x",
- ! CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
- else
- ! fprintf (file, "%d", CONST_DOUBLE_LOW (x));
- }
- ! else
- ! /* We can't handle floating point constants;
- ! PRINT_OPERAND must handle them. */
- ! output_operand_lossage ("floating constant misused");
- ! break;
-
- ! case PLUS:
- ! /* Some assemblers need integer constants to appear last (eg masm). */
- ! if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- {
- ! output_pic_addr_const (file, XEXP (x, 1), code);
- ! if (INTVAL (XEXP (x, 0)) >= 0)
- ! fprintf (file, "+");
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- }
- ! else
- {
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- ! if (INTVAL (XEXP (x, 1)) >= 0)
- ! fprintf (file, "+");
- ! output_pic_addr_const (file, XEXP (x, 1), code);
- }
- ! break;
-
- case MINUS:
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- ! fprintf (file, "-");
- ! output_pic_addr_const (file, XEXP (x, 1), code);
- ! break;
-
- default:
- ! output_operand_lossage ("invalid expression as operand");
- }
- }
- -
- - /* Meaning of CODE:
- - f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
- - D,L,W,B,Q,S -- print the opcode suffix for specified size of operand.
- - R -- print the prefix for register names.
- - z -- print the opcode suffix for the size of the current operand.
- - * -- print a star (in certain assembler syntax)
- - w -- print the operand as if it's a "word" (HImode) even if it isn't.
- - c -- don't print special prefixes before constant operands.
- - J -- print the appropriate jump operand.
- - */
-
- ! void
- ! print_operand (file, x, code)
- ! FILE *file;
- ! rtx x;
- ! int code;
- {
- ! if (code)
- {
- ! switch (code)
- ! {
- ! case '*':
- ! if (USE_STAR)
- ! putc ('*', file);
- ! return;
-
- ! case 'L':
- ! PUT_OP_SIZE (code, 'l', file);
- ! return;
-
- ! case 'W':
- ! PUT_OP_SIZE (code, 'w', file);
- ! return;
-
- ! case 'B':
- ! PUT_OP_SIZE (code, 'b', file);
- ! return;
-
- ! case 'Q':
- ! PUT_OP_SIZE (code, 'l', file);
- ! return;
- !
- ! case 'S':
- ! PUT_OP_SIZE (code, 's', file);
- ! return;
-
- ! case 'T':
- ! PUT_OP_SIZE (code, 't', file);
- ! return;
-
- ! case 'z':
- ! /* 387 opcodes don't get size suffixes if the operands are
- ! registers. */
-
- ! if (STACK_REG_P (x))
- ! return;
-
- ! /* this is the size of op from size of operand */
- ! switch (GET_MODE_SIZE (GET_MODE (x)))
- ! {
- ! case 1:
- ! PUT_OP_SIZE ('B', 'b', file);
- ! return;
-
- ! case 2:
- ! PUT_OP_SIZE ('W', 'w', file);
- ! return;
-
- ! case 4:
- ! if (GET_MODE (x) == SFmode)
- ! {
- ! PUT_OP_SIZE ('S', 's', file);
- ! return;
- ! }
- ! else
- ! PUT_OP_SIZE ('L', 'l', file);
- ! return;
-
- ! case 12:
- ! PUT_OP_SIZE ('T', 't', file);
- ! return;
-
- ! case 8:
- ! if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
- ! {
- ! #ifdef GAS_MNEMONICS
- ! PUT_OP_SIZE ('Q', 'q', file);
- ! return;
- ! #else
- ! PUT_OP_SIZE ('Q', 'l', file); /* Fall through */
- ! #endif
- ! }
-
- ! PUT_OP_SIZE ('Q', 'l', file);
- ! return;
- ! }
-
- ! case 'b':
- ! case 'w':
- ! case 'k':
- ! case 'h':
- ! case 'y':
- ! case 'P':
- ! break;
-
- ! case 'J':
- ! switch (GET_CODE (x))
- ! {
- ! /* These conditions are appropriate for testing the result
- ! of an arithmetic operation, not for a compare operation.
- ! Cases GE, LT assume CC_NO_OVERFLOW true. All cases assume
- ! CC_Z_IN_NOT_C false and not floating point. */
- ! case NE: fputs ("jne", file); return;
- ! case EQ: fputs ("je", file); return;
- ! case GE: fputs ("jns", file); return;
- ! case LT: fputs ("js", file); return;
- ! case GEU: fputs ("jmp", file); return;
- ! case GTU: fputs ("jne", file); return;
- ! case LEU: fputs ("je", file); return;
- ! case LTU: fputs ("#branch never", file); return;
-
- ! /* no matching branches for GT nor LE */
- ! }
- ! abort ();
-
- ! default:
- ! {
- ! char str[50];
-
- ! sprintf (str, "invalid operand code `%c'", code);
- ! output_operand_lossage (str);
- ! }
- ! }
- ! }
- ! if (GET_CODE (x) == REG)
- ! {
- ! PRINT_REG (x, code, file);
- ! }
- ! else if (GET_CODE (x) == MEM)
- ! {
- ! PRINT_PTR (x, file);
- ! if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
- ! {
- ! if (flag_pic)
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- ! else
- ! output_addr_const (file, XEXP (x, 0));
- ! }
- ! else
- ! output_address (XEXP (x, 0));
- ! }
- ! else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
- ! {
- ! REAL_VALUE_TYPE r; long l;
- ! REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- ! REAL_VALUE_TO_TARGET_SINGLE (r, l);
- ! PRINT_IMMED_PREFIX (file);
- ! fprintf (file, "0x%x", l);
- ! }
- ! /* These float cases don't actually occur as immediate operands. */
- ! else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
- ! {
- ! REAL_VALUE_TYPE r; char dstr[30];
- ! REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- ! REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
- ! fprintf (file, "%s", dstr);
- ! }
- ! else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
- ! {
- ! REAL_VALUE_TYPE r; char dstr[30];
- ! REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- ! REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
- ! fprintf (file, "%s", dstr);
- ! }
- ! else
- {
- ! if (code != 'P')
- {
- ! if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
- ! PRINT_IMMED_PREFIX (file);
- ! else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
- ! || GET_CODE (x) == LABEL_REF)
- ! PRINT_OFFSET_PREFIX (file);
- }
- - if (flag_pic)
- - output_pic_addr_const (file, x, code);
- - else
- - output_addr_const (file, x);
- - }
- - }
- -
- - /* Print a memory operand whose address is ADDR. */
- -
- - void
- - print_operand_address (file, addr)
- - FILE *file;
- - register rtx addr;
- - {
- - register rtx reg1, reg2, breg, ireg;
- - rtx offset;
-
- ! switch (GET_CODE (addr))
- ! {
- ! case REG:
- ! ADDR_BEG (file);
- ! fprintf (file, "%se", RP);
- ! fputs (hi_reg_name[REGNO (addr)], file);
- ! ADDR_END (file);
- ! break;
-
- ! case PLUS:
- ! reg1 = 0;
- ! reg2 = 0;
- ! ireg = 0;
- ! breg = 0;
- ! offset = 0;
- ! if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
- {
- ! offset = XEXP (addr, 0);
- ! addr = XEXP (addr, 1);
- }
- ! else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
- {
- ! offset = XEXP (addr, 1);
- ! addr = XEXP (addr, 0);
- }
- ! if (GET_CODE (addr) != PLUS) ;
- ! else if (GET_CODE (XEXP (addr, 0)) == MULT)
- ! {
- ! reg1 = XEXP (addr, 0);
- ! addr = XEXP (addr, 1);
- ! }
- ! else if (GET_CODE (XEXP (addr, 1)) == MULT)
- ! {
- ! reg1 = XEXP (addr, 1);
- ! addr = XEXP (addr, 0);
- ! }
- ! else if (GET_CODE (XEXP (addr, 0)) == REG)
- ! {
- ! reg1 = XEXP (addr, 0);
- ! addr = XEXP (addr, 1);
- ! }
- ! else if (GET_CODE (XEXP (addr, 1)) == REG)
- ! {
- ! reg1 = XEXP (addr, 1);
- ! addr = XEXP (addr, 0);
- ! }
- ! if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
- ! {
- ! if (reg1 == 0) reg1 = addr;
- ! else reg2 = addr;
- ! addr = 0;
- ! }
- ! if (offset != 0)
- {
- ! if (addr != 0) abort ();
- ! addr = offset;
- }
- ! if ((reg1 && GET_CODE (reg1) == MULT)
- ! || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
- {
- ! breg = reg2;
- ! ireg = reg1;
- }
- ! else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
- {
- ! breg = reg1;
- ! ireg = reg2;
- }
-
- ! if (ireg != 0 || breg != 0)
- ! {
- ! int scale = 1;
-
- ! if (addr != 0)
- ! {
- ! if (flag_pic)
- ! output_pic_addr_const (file, addr, 0);
-
- ! else if (GET_CODE (addr) == LABEL_REF)
- ! output_asm_label (addr);
-
- ! else
- ! output_addr_const (file, addr);
- ! }
-
- ! if (ireg != 0 && GET_CODE (ireg) == MULT)
- ! {
- ! scale = INTVAL (XEXP (ireg, 1));
- ! ireg = XEXP (ireg, 0);
- ! }
-
- ! /* The stack pointer can only appear as a base register,
- ! never an index register, so exchange the regs if it is wrong. */
-
- ! if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
- ! {
- ! rtx tmp;
-
- ! tmp = breg;
- ! breg = ireg;
- ! ireg = tmp;
- ! }
-
- ! /* output breg+ireg*scale */
- ! PRINT_B_I_S (breg, ireg, scale, file);
- ! break;
- ! }
-
- ! case MULT:
- ! {
- ! int scale;
- ! if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
- ! {
- ! scale = INTVAL (XEXP (addr, 0));
- ! ireg = XEXP (addr, 1);
- ! }
- ! else
- ! {
- ! scale = INTVAL (XEXP (addr, 1));
- ! ireg = XEXP (addr, 0);
- ! }
- ! output_addr_const (file, const0_rtx);
- ! PRINT_B_I_S ((rtx) 0, ireg, scale, file);
- ! }
- ! break;
-
- ! default:
- ! if (GET_CODE (addr) == CONST_INT
- ! && INTVAL (addr) < 0x8000
- ! && INTVAL (addr) >= -0x8000)
- ! fprintf (file, "%d", INTVAL (addr));
- else
- ! {
- ! if (flag_pic)
- ! output_pic_addr_const (file, addr, 0);
- ! else
- ! output_addr_const (file, addr);
- ! }
- }
- }
-
- ! /* Set the cc_status for the results of an insn whose pattern is EXP.
- ! On the 80386, we assume that only test and compare insns, as well
- ! as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT,
- ! ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
- ! Also, we assume that jumps, moves and sCOND don't affect the condition
- ! codes. All else clobbers the condition codes, by assumption.
-
- ! We assume that ALL integer add, minus, etc. instructions effect the
- ! condition codes. This MUST be consistent with i386.md.
-
- ! We don't record any float test or compare - the redundant test &
- ! compare check in final.c does not handle stack-like regs correctly. */
-
- ! void
- ! notice_update_cc (exp)
- ! rtx exp;
- ! {
- ! if (GET_CODE (exp) == SET)
- {
- ! /* Jumps do not alter the cc's. */
- ! if (SET_DEST (exp) == pc_rtx)
- ! return;
- ! /* Moving register or memory into a register:
- ! it doesn't alter the cc's, but it might invalidate
- ! the RTX's which we remember the cc's came from.
- ! (Note that moving a constant 0 or 1 MAY set the cc's). */
- ! if (REG_P (SET_DEST (exp))
- ! && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
- ! || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
- ! {
- ! if (cc_status.value1
- ! && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
- ! cc_status.value1 = 0;
- ! if (cc_status.value2
- ! && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
- ! cc_status.value2 = 0;
- ! return;
- ! }
- ! /* Moving register into memory doesn't alter the cc's.
- ! It may invalidate the RTX's which we remember the cc's came from. */
- ! if (GET_CODE (SET_DEST (exp)) == MEM
- ! && (REG_P (SET_SRC (exp))
- ! || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
- ! {
- ! if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
- ! cc_status.value1 = 0;
- ! if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
- ! cc_status.value2 = 0;
- ! return;
- ! }
- ! /* Function calls clobber the cc's. */
- ! else if (GET_CODE (SET_SRC (exp)) == CALL)
- ! {
- ! CC_STATUS_INIT;
- ! return;
- ! }
- ! /* Tests and compares set the cc's in predictable ways. */
- ! else if (SET_DEST (exp) == cc0_rtx)
- ! {
- ! CC_STATUS_INIT;
- ! cc_status.value1 = SET_SRC (exp);
- ! return;
- ! }
- ! /* Certain instructions effect the condition codes. */
- ! else if (GET_MODE (SET_SRC (exp)) == SImode
- ! || GET_MODE (SET_SRC (exp)) == HImode
- ! || GET_MODE (SET_SRC (exp)) == QImode)
- ! switch (GET_CODE (SET_SRC (exp)))
- ! {
- ! case ASHIFTRT: case LSHIFTRT:
- ! case ASHIFT:
- ! /* Shifts on the 386 don't set the condition codes if the
- ! shift count is zero. */
- ! if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
- ! {
- ! CC_STATUS_INIT;
- ! break;
- ! }
- ! /* We assume that the CONST_INT is non-zero (this rtx would
- ! have been deleted if it were zero. */
-
- ! case PLUS: case MINUS: case NEG:
- ! case AND: case IOR: case XOR:
- ! cc_status.flags = CC_NO_OVERFLOW;
- ! cc_status.value1 = SET_SRC (exp);
- ! cc_status.value2 = SET_DEST (exp);
- ! break;
-
- ! default:
- ! CC_STATUS_INIT;
- ! }
- ! else
- ! {
- ! CC_STATUS_INIT;
- ! }
- }
- ! else if (GET_CODE (exp) == PARALLEL
- ! && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
- {
- ! if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
- ! return;
- ! if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
- ! {
- ! CC_STATUS_INIT;
- ! if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
- ! cc_status.flags |= CC_IN_80387;
- ! else
- ! cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
- ! return;
- ! }
- ! CC_STATUS_INIT;
- }
- else
- {
- ! CC_STATUS_INIT;
- }
- }
- -
- - /* Split one or more DImode RTL references into pairs of SImode
- - references. The RTL can be REG, offsettable MEM, integer constant, or
- - CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
- - split and "num" is its length. lo_half and hi_half are output arrays
- - that parallel "operands". */
-
- void
- ! split_di (operands, num, lo_half, hi_half)
- ! rtx operands[];
- ! int num;
- ! rtx lo_half[], hi_half[];
- {
- ! while (num--)
- ! {
- ! if (GET_CODE (operands[num]) == REG)
- ! {
- ! lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
- ! hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
- ! }
- ! else if (CONSTANT_P (operands[num]))
- ! {
- ! split_double (operands[num], &lo_half[num], &hi_half[num]);
- ! }
- ! else if (offsettable_memref_p (operands[num]))
- ! {
- ! lo_half[num] = operands[num];
- ! hi_half[num] = adj_offsettable_operand (operands[num], 4);
- ! }
- ! else
- ! abort();
- ! }
- }
- -
- - /* Return 1 if this is a valid binary operation on a 387.
- - OP is the expression matched, and MODE is its mode. */
-
- ! int
- ! binary_387_op (op, mode)
- ! register rtx op;
- ! enum machine_mode mode;
- {
- ! if (mode != VOIDmode && mode != GET_MODE (op))
- ! return 0;
-
- ! switch (GET_CODE (op))
- ! {
- ! case PLUS:
- ! case MINUS:
- ! case MULT:
- ! case DIV:
- ! return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
-
- ! default:
- ! return 0;
- ! }
- }
-
- !
- ! /* Return 1 if this is a valid shift or rotate operation on a 386.
- ! OP is the expression matched, and MODE is its mode. */
-
- ! int
- ! shift_op (op, mode)
- ! register rtx op;
- ! enum machine_mode mode;
- {
- ! rtx operand = XEXP (op, 0);
-
- ! if (mode != VOIDmode && mode != GET_MODE (op))
- ! return 0;
-
- - if (GET_MODE (operand) != GET_MODE (op)
- - || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
- - return 0;
-
- ! return (GET_CODE (op) == ASHIFT
- ! || GET_CODE (op) == ASHIFTRT
- ! || GET_CODE (op) == LSHIFTRT
- ! || GET_CODE (op) == ROTATE
- ! || GET_CODE (op) == ROTATERT);
- }
-
- ! /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
- ! MODE is not used. */
- !
- ! int
- ! VOIDmode_compare_op (op, mode)
- register rtx op;
- enum machine_mode mode;
- {
- ! return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode;
- }
- -
- - /* Output code to perform a 387 binary operation in INSN, one of PLUS,
- - MINUS, MULT or DIV. OPERANDS are the insn operands, where operands[3]
- - is the expression of the binary operation. The output may either be
- - emitted here, or returned to the caller, like all output_* functions.
-
- ! There is no guarantee that the operands are the same mode, as they
- ! might be within FLOAT or FLOAT_EXTEND expressions. */
-
- ! char *
- ! output_387_binary_op (insn, operands)
- ! rtx insn;
- ! rtx *operands;
- {
- ! rtx temp;
- ! char *base_op;
- ! static char buf[100];
-
- ! switch (GET_CODE (operands[3]))
- {
- ! case PLUS:
- ! if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- ! || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- ! base_op = "fiadd";
- ! else
- ! base_op = "fadd";
- ! break;
-
- ! case MINUS:
- ! if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- ! || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- ! base_op = "fisub";
- ! else
- ! base_op = "fsub";
- break;
-
- ! case MULT:
- ! if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- ! || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- ! base_op = "fimul";
- ! else
- ! base_op = "fmul";
- ! break;
-
- ! case DIV:
- ! if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- ! || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- ! base_op = "fidiv";
- ! else
- ! base_op = "fdiv";
- ! break;
-
- ! default:
- ! abort ();
- }
- !
- ! strcpy (buf, base_op);
- !
- ! switch (GET_CODE (operands[3]))
- {
- ! case MULT:
- ! case PLUS:
- ! if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
- {
- ! temp = operands[2];
- ! operands[2] = operands[1];
- ! operands[1] = temp;
- }
- !
- ! if (GET_CODE (operands[2]) == MEM)
- ! return strcat (buf, AS1 (%z2,%2));
- !
- ! if (NON_STACK_REG_P (operands[1]))
- {
- ! output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
- ! RET;
- }
- ! else if (NON_STACK_REG_P (operands[2]))
- {
- ! output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
- ! RET;
- }
- -
- - if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
- - return strcat (buf, AS2 (p,%2,%0));
- -
- - if (STACK_TOP_P (operands[0]))
- - return strcat (buf, AS2C (%y2,%0));
- else
- - return strcat (buf, AS2C (%2,%0));
- -
- - case MINUS:
- - case DIV:
- - if (GET_CODE (operands[1]) == MEM)
- - return strcat (buf, AS1 (r%z1,%1));
- -
- - if (GET_CODE (operands[2]) == MEM)
- - return strcat (buf, AS1 (%z2,%2));
- -
- - if (NON_STACK_REG_P (operands[1]))
- {
- ! output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
- ! RET;
- }
- ! else if (NON_STACK_REG_P (operands[2]))
- {
- ! output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
- ! RET;
- }
- !
- ! if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
- ! abort ();
- !
- ! if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
- ! return strcat (buf, AS2 (rp,%2,%0));
- !
- ! if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- ! return strcat (buf, AS2 (p,%1,%0));
- !
- ! if (STACK_TOP_P (operands[0]))
- {
- ! if (STACK_TOP_P (operands[1]))
- ! return strcat (buf, AS2C (%y2,%0));
- else
- ! return strcat (buf, AS2 (r,%y1,%0));
- }
- ! else if (STACK_TOP_P (operands[1]))
- ! return strcat (buf, AS2C (%1,%0));
- ! else
- ! return strcat (buf, AS2 (r,%2,%0));
- !
- ! default:
- ! abort ();
- }
- }
- -
- - /* Output code for INSN to convert a float to a signed int. OPERANDS
- - are the insn operands. The output may be SFmode or DFmode and the
- - input operand may be SImode or DImode. As a special case, make sure
- - that the 387 stack top dies if the output mode is DImode, because the
- - hardware requires this. */
-
- ! char *
- ! output_fix_trunc (insn, operands)
- ! rtx insn;
- ! rtx *operands;
- {
- ! int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- ! rtx xops[2];
-
- ! if (! STACK_TOP_P (operands[1]) ||
- ! (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
- ! abort ();
- !
- ! xops[0] = GEN_INT (12);
- ! xops[1] = operands[4];
- !
- ! output_asm_insn (AS1 (fnstc%W2,%2), operands);
- ! output_asm_insn (AS2 (mov%L2,%2,%4), operands);
- ! output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
- ! output_asm_insn (AS2 (mov%L4,%4,%3), operands);
- ! output_asm_insn (AS1 (fldc%W3,%3), operands);
- !
- ! if (NON_STACK_REG_P (operands[0]))
- ! output_to_reg (operands[0], stack_top_dies);
- ! else if (GET_CODE (operands[0]) == MEM)
- {
- ! if (stack_top_dies)
- ! output_asm_insn (AS1 (fistp%z0,%0), operands);
- else
- ! output_asm_insn (AS1 (fist%z0,%0), operands);
- }
- ! else
- ! abort ();
- !
- ! return AS1 (fldc%W2,%2);
- }
- -
- - /* Output code for INSN to compare OPERANDS. The two operands might
- - not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
- - expression. If the compare is in mode CCFPEQmode, use an opcode that
- - will not fault if a qNaN is present. */
-
- ! char *
- ! output_float_compare (insn, operands)
- ! rtx insn;
- ! rtx *operands;
- {
- ! int stack_top_dies;
- ! rtx body = XVECEXP (PATTERN (insn), 0, 0);
- ! int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
- !
- ! if (! STACK_TOP_P (operands[0]))
- ! abort ();
- !
- ! stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- !
- ! if (STACK_REG_P (operands[1])
- ! && stack_top_dies
- ! && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
- ! && REGNO (operands[1]) != FIRST_STACK_REG)
- ! {
- ! /* If both the top of the 387 stack dies, and the other operand
- ! is also a stack register that dies, then this must be a
- ! `fcompp' float compare */
- !
- ! if (unordered_compare)
- ! output_asm_insn ("fucompp", operands);
- ! else
- ! output_asm_insn ("fcompp", operands);
- ! }
- ! else
- {
- ! static char buf[100];
- !
- ! /* Decide if this is the integer or float compare opcode, or the
- ! unordered float compare. */
- !
- ! if (unordered_compare)
- ! strcpy (buf, "fucom");
- ! else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
- ! strcpy (buf, "fcom");
- ! else
- ! strcpy (buf, "ficom");
- !
- ! /* Modify the opcode if the 387 stack is to be popped. */
- !
- ! if (stack_top_dies)
- ! strcat (buf, "p");
- !
- ! if (NON_STACK_REG_P (operands[1]))
- ! output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
- ! else
- ! output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
- ! }
-
- ! /* Now retrieve the condition code. */
-
- ! return output_fp_cc0_set (insn);
- }
- -
- - /* Output opcodes to transfer the results of FP compare or test INSN
- - from the FPU to the CPU flags. If TARGET_IEEE_FP, ensure that if the
- - result of the compare or test is unordered, no comparison operator
- - succeeds except NE. Return an output template, if any. */
-
- ! char *
- ! output_fp_cc0_set (insn)
- ! rtx insn;
- {
- ! rtx xops[3];
- ! rtx unordered_label;
- ! rtx next;
- ! enum rtx_code code;
-
- ! xops[0] = gen_rtx (REG, HImode, 0);
- ! output_asm_insn (AS1 (fnsts%W0,%0), xops);
-
- ! if (! TARGET_IEEE_FP)
- ! return "sahf";
-
- - next = next_cc0_user (insn);
- - if (next == NULL_RTX)
- - abort ();
-
- ! if (GET_CODE (next) == JUMP_INSN
- ! && GET_CODE (PATTERN (next)) == SET
- ! && SET_DEST (PATTERN (next)) == pc_rtx
- ! && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
- ! {
- ! code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
- ! }
- ! else if (GET_CODE (PATTERN (next)) == SET)
- {
- ! code = GET_CODE (SET_SRC (PATTERN (next)));
- }
- ! else
- ! abort ();
-
- ! xops[0] = gen_rtx (REG, QImode, 0);
-
- ! switch (code)
- {
- ! case GT:
- ! xops[1] = GEN_INT (0x45);
- ! output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- ! /* je label */
- ! break;
-
- - case LT:
- - xops[1] = GEN_INT (0x45);
- - xops[2] = GEN_INT (0x01);
- - output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- - output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- - /* je label */
- - break;
-
- ! case GE:
- ! xops[1] = GEN_INT (0x05);
- ! output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- ! /* je label */
- ! break;
-
- - case LE:
- - xops[1] = GEN_INT (0x45);
- - xops[2] = GEN_INT (0x40);
- - output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- - output_asm_insn (AS1 (dec%B0,%h0), xops);
- - output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- - /* jb label */
- - break;
-
- - case EQ:
- - xops[1] = GEN_INT (0x45);
- - xops[2] = GEN_INT (0x40);
- - output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- - output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- - /* je label */
- - break;
-
- - case NE:
- - xops[1] = GEN_INT (0x44);
- - xops[2] = GEN_INT (0x40);
- - output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- - output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
- - /* jne label */
- - break;
-
- ! case GTU:
- ! case LTU:
- ! case GEU:
- ! case LEU:
- ! default:
- ! abort ();
- }
- ! RET;
- }
- -
- - #define MAX_386_STACK_LOCALS 2
-
- ! static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
-
- ! /* Define the structure for the machine field in struct function. */
- ! struct machine_function
- {
- ! rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
- ! };
-
- - /* Functions to save and restore i386_stack_locals.
- - These will be called, via pointer variables,
- - from push_function_context and pop_function_context. */
-
- ! void
- ! save_386_machine_status (p)
- ! struct function *p;
- {
- ! p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals);
- ! bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals,
- ! sizeof i386_stack_locals);
- }
-
- ! void
- ! restore_386_machine_status (p)
- ! struct function *p;
- {
- ! bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals,
- ! sizeof i386_stack_locals);
- ! free (p->machine);
- }
-
- - /* Clear stack slot assignments remembered from previous functions.
- - This is called from INIT_EXPANDERS once before RTL is emitted for each
- - function. */
-
- ! void
- ! clear_386_stack_locals ()
- {
- ! enum machine_mode mode;
- ! int n;
-
- ! for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
- ! mode = (enum machine_mode) ((int) mode + 1))
- ! for (n = 0; n < MAX_386_STACK_LOCALS; n++)
- ! i386_stack_locals[(int) mode][n] = NULL_RTX;
-
- ! /* Arrange to save and restore i386_stack_locals around nested functions. */
- ! save_machine_status = save_386_machine_status;
- ! restore_machine_status = restore_386_machine_status;
- ! }
-
- ! /* Return a MEM corresponding to a stack slot with mode MODE.
- ! Allocate a new slot if necessary.
-
- ! The RTL for a function can have several slots available: N is
- ! which slot to use. */
-
- - rtx
- - assign_386_stack_local (mode, n)
- - enum machine_mode mode;
- - int n;
- - {
- - if (n < 0 || n >= MAX_386_STACK_LOCALS)
- - abort ();
-
- ! if (i386_stack_locals[(int) mode][n] == NULL_RTX)
- ! i386_stack_locals[(int) mode][n]
- ! = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
-
- ! return i386_stack_locals[(int) mode][n];
- }
- --- 1429,3510 ----
- else
- output_asm_insn ("ret", xops);
- }
-
- ! /* Print an integer constant expression in assembler syntax. Addition
- ! and subtraction are the only arithmetic that may appear in these
- ! expressions. FILE is the stdio stream to write to, X is the rtx, and
- ! CODE is the operand print code from the output string. */
-
- ! static void
- ! output_pic_addr_const (file, x, code)
- ! FILE *file;
- ! rtx x;
- ! int code;
- {
- ! char buf[256];
-
- ! switch (GET_CODE (x))
- {
- ! case PC:
- ! if (flag_pic)
- ! putc ('.', file);
- ! else
- ! abort ();
- ! break;
-
- ! case SYMBOL_REF:
- ! case LABEL_REF:
- ! if (GET_CODE (x) == SYMBOL_REF)
- ! assemble_name (file, XSTR (x, 0));
- ! else
- {
- ! ASM_GENERATE_INTERNAL_LABEL (buf, "L",
- ! CODE_LABEL_NUMBER (XEXP (x, 0)));
- ! assemble_name (asm_out_file, buf);
- }
-
- + if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
- + fprintf (file, "@GOTOFF(%%ebx)");
- + else if (code == 'P')
- + fprintf (file, "@PLT");
- + else if (GET_CODE (x) == LABEL_REF || ! SYMBOL_REF_FLAG (x))
- + fprintf (file, "@GOT");
- else
- ! fprintf (file, "@GOTOFF");
-
- ! break;
-
- ! case CODE_LABEL:
- ! ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
- ! assemble_name (asm_out_file, buf);
- ! break;
-
- ! case CONST_INT:
- ! fprintf (file, "%d", INTVAL (x));
- ! break;
-
- ! case CONST:
- ! /* This used to output parentheses around the expression,
- ! but that does not work on the 386 (either ATT or BSD assembler). */
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- ! break;
-
- ! case CONST_DOUBLE:
- ! if (GET_MODE (x) == VOIDmode)
- {
- ! /* We can use %d if the number is <32 bits and positive. */
- ! if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
- ! fprintf (file, "0x%x%08x",
- ! CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
- ! else
- ! fprintf (file, "%d", CONST_DOUBLE_LOW (x));
- }
- ! else
- ! /* We can't handle floating point constants;
- ! PRINT_OPERAND must handle them. */
- ! output_operand_lossage ("floating constant misused");
- ! break;
-
- ! case PLUS:
- ! /* Some assemblers need integer constants to appear last (eg masm). */
- ! if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- {
- ! output_pic_addr_const (file, XEXP (x, 1), code);
- ! if (INTVAL (XEXP (x, 0)) >= 0)
- ! fprintf (file, "+");
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- }
- ! else
- {
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- ! if (INTVAL (XEXP (x, 1)) >= 0)
- ! fprintf (file, "+");
- ! output_pic_addr_const (file, XEXP (x, 1), code);
- }
- ! break;
-
- ! case MINUS:
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- ! fprintf (file, "-");
- ! output_pic_addr_const (file, XEXP (x, 1), code);
- ! break;
-
- ! default:
- ! output_operand_lossage ("invalid expression as operand");
- }
- + }
- +
- + /* Meaning of CODE:
- + f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
- + D,L,W,B,Q,S -- print the opcode suffix for specified size of operand.
- + R -- print the prefix for register names.
- + z -- print the opcode suffix for the size of the current operand.
- + * -- print a star (in certain assembler syntax)
- + w -- print the operand as if it's a "word" (HImode) even if it isn't.
- + c -- don't print special prefixes before constant operands.
- + J -- print the appropriate jump operand.
- + */
-
- ! void
- ! print_operand (file, x, code)
- ! FILE *file;
- ! rtx x;
- ! int code;
- ! {
- ! if (code)
- {
- ! switch (code)
- {
- ! case '*':
- ! if (USE_STAR)
- ! putc ('*', file);
- ! return;
-
- ! case 'L':
- ! PUT_OP_SIZE (code, 'l', file);
- ! return;
-
- ! case 'W':
- ! PUT_OP_SIZE (code, 'w', file);
- ! return;
-
- ! case 'B':
- ! PUT_OP_SIZE (code, 'b', file);
- ! return;
-
- ! case 'Q':
- ! PUT_OP_SIZE (code, 'l', file);
- ! return;
-
- ! case 'S':
- ! PUT_OP_SIZE (code, 's', file);
- ! return;
-
- ! case 'T':
- ! PUT_OP_SIZE (code, 't', file);
- ! return;
-
- ! case 'z':
- ! /* 387 opcodes don't get size suffixes if the operands are
- ! registers. */
-
- ! if (STACK_REG_P (x))
- ! return;
-
- ! /* this is the size of op from size of operand */
- ! switch (GET_MODE_SIZE (GET_MODE (x)))
- ! {
- ! case 1:
- ! PUT_OP_SIZE ('B', 'b', file);
- ! return;
-
- ! case 2:
- ! PUT_OP_SIZE ('W', 'w', file);
- ! return;
-
- ! case 4:
- ! if (GET_MODE (x) == SFmode)
- ! {
- ! PUT_OP_SIZE ('S', 's', file);
- ! return;
- ! }
- ! else
- ! PUT_OP_SIZE ('L', 'l', file);
- ! return;
-
- ! case 12:
- ! PUT_OP_SIZE ('T', 't', file);
- ! return;
-
- ! case 8:
- ! if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
- ! {
- ! #ifdef GAS_MNEMONICS
- ! PUT_OP_SIZE ('Q', 'q', file);
- ! return;
- ! #else
- ! PUT_OP_SIZE ('Q', 'l', file); /* Fall through */
- ! #endif
- ! }
-
- ! PUT_OP_SIZE ('Q', 'l', file);
- ! return;
- ! }
-
- ! case 'b':
- ! case 'w':
- ! case 'k':
- ! case 'h':
- ! case 'y':
- ! case 'P':
- ! break;
-
- ! case 'J':
- ! switch (GET_CODE (x))
- ! {
- ! /* These conditions are appropriate for testing the result
- ! of an arithmetic operation, not for a compare operation.
- ! Cases GE, LT assume CC_NO_OVERFLOW true. All cases assume
- ! CC_Z_IN_NOT_C false and not floating point. */
- ! case NE: fputs ("jne", file); return;
- ! case EQ: fputs ("je", file); return;
- ! case GE: fputs ("jns", file); return;
- ! case LT: fputs ("js", file); return;
- ! case GEU: fputs ("jmp", file); return;
- ! case GTU: fputs ("jne", file); return;
- ! case LEU: fputs ("je", file); return;
- ! case LTU: fputs ("#branch never", file); return;
-
- ! /* no matching branches for GT nor LE */
- ! }
- ! abort ();
-
- ! default:
- ! {
- ! char str[50];
-
- ! sprintf (str, "invalid operand code `%c'", code);
- ! output_operand_lossage (str);
- ! }
- ! }
- ! }
- ! if (GET_CODE (x) == REG)
- ! {
- ! PRINT_REG (x, code, file);
- ! }
- ! else if (GET_CODE (x) == MEM)
- ! {
- ! PRINT_PTR (x, file);
- ! if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
- {
- ! if (flag_pic)
- ! output_pic_addr_const (file, XEXP (x, 0), code);
- ! else
- ! output_addr_const (file, XEXP (x, 0));
- }
- ! else
- ! output_address (XEXP (x, 0));
- ! }
- ! else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
- ! {
- ! REAL_VALUE_TYPE r; long l;
- ! REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- ! REAL_VALUE_TO_TARGET_SINGLE (r, l);
- ! PRINT_IMMED_PREFIX (file);
- ! fprintf (file, "0x%x", l);
- ! }
- ! /* These float cases don't actually occur as immediate operands. */
- ! else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
- ! {
- ! REAL_VALUE_TYPE r; char dstr[30];
- ! REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- ! REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
- ! fprintf (file, "%s", dstr);
- ! }
- ! else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
- ! {
- ! REAL_VALUE_TYPE r; char dstr[30];
- ! REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- ! REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
- ! fprintf (file, "%s", dstr);
- ! }
- ! else
- ! {
- ! if (code != 'P')
- ! {
- ! if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
- ! PRINT_IMMED_PREFIX (file);
- ! else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
- ! || GET_CODE (x) == LABEL_REF)
- ! PRINT_OFFSET_PREFIX (file);
- ! }
- ! if (flag_pic)
- ! output_pic_addr_const (file, x, code);
- ! else
- ! output_addr_const (file, x);
- }
- }
-
- ! /* Print a memory operand whose address is ADDR. */
-
- void
- ! print_operand_address (file, addr)
- ! FILE *file;
- ! register rtx addr;
- {
- ! register rtx reg1, reg2, breg, ireg;
- ! rtx offset;
-
- ! switch (GET_CODE (addr))
- {
- ! case REG:
- ! ADDR_BEG (file);
- ! fprintf (file, "%se", RP);
- ! fputs (hi_reg_name[REGNO (addr)], file);
- ! ADDR_END (file);
- ! break;
-
- ! case PLUS:
- ! reg1 = 0;
- ! reg2 = 0;
- ! ireg = 0;
- ! breg = 0;
- ! offset = 0;
- ! if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
- {
- ! offset = XEXP (addr, 0);
- ! addr = XEXP (addr, 1);
- }
- ! else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
- {
- ! offset = XEXP (addr, 1);
- ! addr = XEXP (addr, 0);
- }
- ! if (GET_CODE (addr) != PLUS) ;
- ! else if (GET_CODE (XEXP (addr, 0)) == MULT)
- {
- ! reg1 = XEXP (addr, 0);
- ! addr = XEXP (addr, 1);
- }
- ! else if (GET_CODE (XEXP (addr, 1)) == MULT)
- ! {
- ! reg1 = XEXP (addr, 1);
- ! addr = XEXP (addr, 0);
- ! }
- ! else if (GET_CODE (XEXP (addr, 0)) == REG)
- ! {
- ! reg1 = XEXP (addr, 0);
- ! addr = XEXP (addr, 1);
- ! }
- ! else if (GET_CODE (XEXP (addr, 1)) == REG)
- ! {
- ! reg1 = XEXP (addr, 1);
- ! addr = XEXP (addr, 0);
- ! }
- ! if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
- ! {
- ! if (reg1 == 0) reg1 = addr;
- ! else reg2 = addr;
- ! addr = 0;
- ! }
- ! if (offset != 0)
- ! {
- ! if (addr != 0) abort ();
- ! addr = offset;
- ! }
- ! if ((reg1 && GET_CODE (reg1) == MULT)
- ! || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
- ! {
- ! breg = reg2;
- ! ireg = reg1;
- ! }
- ! else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
- {
- ! breg = reg1;
- ! ireg = reg2;
- }
-
- ! if (ireg != 0 || breg != 0)
- {
- ! int scale = 1;
-
- ! if (addr != 0)
- {
- ! if (GET_CODE (addr) == LABEL_REF)
- ! output_asm_label (addr);
- ! else
- ! {
- ! if (flag_pic)
- ! output_pic_addr_const (file, addr, 0);
- ! else
- ! output_addr_const (file, addr);
- ! }
- }
-
- ! if (ireg != 0 && GET_CODE (ireg) == MULT)
- {
- ! scale = INTVAL (XEXP (ireg, 1));
- ! ireg = XEXP (ireg, 0);
- }
-
- ! /* The stack pointer can only appear as a base register,
- ! never an index register, so exchange the regs if it is wrong. */
-
- ! if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
- ! {
- ! rtx tmp;
-
- ! tmp = breg;
- ! breg = ireg;
- ! ireg = tmp;
- ! }
-
- ! /* output breg+ireg*scale */
- ! PRINT_B_I_S (breg, ireg, scale, file);
- ! break;
- }
-
- ! case MULT:
- ! {
- ! int scale;
- ! if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
- ! {
- ! scale = INTVAL (XEXP (addr, 0));
- ! ireg = XEXP (addr, 1);
- ! }
- ! else
- ! {
- ! scale = INTVAL (XEXP (addr, 1));
- ! ireg = XEXP (addr, 0);
- ! }
- ! output_addr_const (file, const0_rtx);
- ! PRINT_B_I_S ((rtx) 0, ireg, scale, file);
- ! }
- ! break;
-
- ! default:
- ! if (GET_CODE (addr) == CONST_INT
- ! && INTVAL (addr) < 0x8000
- ! && INTVAL (addr) >= -0x8000)
- ! fprintf (file, "%d", INTVAL (addr));
- ! else
- {
- ! if (flag_pic)
- ! output_pic_addr_const (file, addr, 0);
- ! else
- ! output_addr_const (file, addr);
- }
- }
- }
-
- ! /* Set the cc_status for the results of an insn whose pattern is EXP.
- ! On the 80386, we assume that only test and compare insns, as well
- ! as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, LSHIFT,
- ! ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
- ! Also, we assume that jumps, moves and sCOND don't affect the condition
- ! codes. All else clobbers the condition codes, by assumption.
-
- ! We assume that ALL integer add, minus, etc. instructions effect the
- ! condition codes. This MUST be consistent with i386.md.
-
- ! We don't record any float test or compare - the redundant test &
- ! compare check in final.c does not handle stack-like regs correctly. */
- !
- ! void
- ! notice_update_cc (exp)
- ! rtx exp;
- ! {
- ! if (GET_CODE (exp) == SET)
- {
- ! /* Jumps do not alter the cc's. */
- ! if (SET_DEST (exp) == pc_rtx)
- ! return;
- ! #ifdef IS_STACK_MODE
- ! /* intel1
- ! Moving into a memory of stack_mode may have been moved
- ! in between the use and set of cc0 by loop_spl(). So
- ! old value of cc.status must be retained */
- ! if(GET_CODE(SET_DEST(exp))==MEM
- ! && IS_STACK_MODE(GET_MODE(SET_DEST(exp))))
- ! {
- ! return;
- ! }
- ! #endif
- ! /* Moving register or memory into a register:
- ! it doesn't alter the cc's, but it might invalidate
- ! the RTX's which we remember the cc's came from.
- ! (Note that moving a constant 0 or 1 MAY set the cc's). */
- ! if (REG_P (SET_DEST (exp))
- ! && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
- ! || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
- {
- ! if (cc_status.value1
- ! && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
- ! cc_status.value1 = 0;
- ! if (cc_status.value2
- ! && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
- ! cc_status.value2 = 0;
- ! return;
- }
- + /* Moving register into memory doesn't alter the cc's.
- + It may invalidate the RTX's which we remember the cc's came from. */
- + if (GET_CODE (SET_DEST (exp)) == MEM
- + && (REG_P (SET_SRC (exp))
- + || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
- + {
- + if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
- + cc_status.value1 = 0;
- + if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
- + cc_status.value2 = 0;
- + return;
- + }
- + /* Function calls clobber the cc's. */
- + else if (GET_CODE (SET_SRC (exp)) == CALL)
- + {
- + CC_STATUS_INIT;
- + return;
- + }
- + /* Tests and compares set the cc's in predictable ways. */
- + else if (SET_DEST (exp) == cc0_rtx)
- + {
- + CC_STATUS_INIT;
- + cc_status.value1 = SET_SRC (exp);
- + return;
- + }
- + /* Certain instructions effect the condition codes. */
- + else if (GET_MODE (SET_SRC (exp)) == SImode
- + || GET_MODE (SET_SRC (exp)) == HImode
- + || GET_MODE (SET_SRC (exp)) == QImode)
- + switch (GET_CODE (SET_SRC (exp)))
- + {
- + case ASHIFTRT: case LSHIFTRT:
- + case ASHIFT: case LSHIFT:
- + /* Shifts on the 386 don't set the condition codes if the
- + shift count is zero. */
- + if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
- + {
- + CC_STATUS_INIT;
- + break;
- + }
- + /* We assume that the CONST_INT is non-zero (this rtx would
- + have been deleted if it were zero. */
-
- ! case PLUS: case MINUS: case NEG:
- ! case AND: case IOR: case XOR:
- ! cc_status.flags = CC_NO_OVERFLOW;
- ! cc_status.value1 = SET_SRC (exp);
- ! cc_status.value2 = SET_DEST (exp);
- ! break;
-
- ! default:
- ! CC_STATUS_INIT;
- ! }
- ! else
- {
- ! CC_STATUS_INIT;
- ! }
- ! }
- ! else if (GET_CODE (exp) == PARALLEL
- ! && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
- ! {
- ! if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
- ! return;
- ! if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
- ! {
- ! CC_STATUS_INIT;
- ! if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
- ! cc_status.flags |= CC_IN_80387;
- else
- ! cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
- ! return;
- }
- ! CC_STATUS_INIT;
- ! }
- ! else
- ! {
- ! CC_STATUS_INIT;
- ! }
- ! }
- !
- ! /* Split one or more DImode RTL references into pairs of SImode
- ! references. The RTL can be REG, offsettable MEM, integer constant, or
- ! CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
- ! split and "num" is its length. lo_half and hi_half are output arrays
- ! that parallel "operands". */
-
- ! void
- ! split_di (operands, num, lo_half, hi_half)
- ! rtx operands[];
- ! int num;
- ! rtx lo_half[], hi_half[];
- ! {
- ! while (num--)
- ! {
- ! if (GET_CODE (operands[num]) == REG)
- {
- ! lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
- ! hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
- }
- ! else if (CONSTANT_P (operands[num]))
- {
- ! split_double (operands[num], &lo_half[num], &hi_half[num]);
- }
- ! else if (offsettable_memref_p (operands[num]))
- ! {
- ! lo_half[num] = operands[num];
- ! hi_half[num] = adj_offsettable_operand (operands[num], 4);
- ! }
- ! else
- ! abort();
- ! }
- ! }
- !
- ! /* Return 1 if this is a valid binary operation on a 387.
- ! OP is the expression matched, and MODE is its mode. */
- !
- ! int
- ! binary_387_op (op, mode)
- ! register rtx op;
- ! enum machine_mode mode;
- ! {
- ! if (mode != VOIDmode && mode != GET_MODE (op))
- ! return 0;
-
- + switch (GET_CODE (op))
- + {
- + case PLUS:
- case MINUS:
- ! case MULT:
- ! case DIV:
- ! return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
-
- default:
- ! return 0;
- }
- }
-
- ! /* Return 1 if this is a valid conversion operation on a 387.
- ! OP is the expression matched, and MODE is its mode. */
- !
- ! int
- ! convert_387_op (op, mode)
- ! register rtx op;
- ! enum machine_mode mode;
- {
- ! if (mode != VOIDmode && mode != GET_MODE (op))
- ! return 0;
- !
- ! switch (GET_CODE (op))
- {
- ! case FLOAT:
- ! return GET_MODE (XEXP (op, 0)) == SImode;
-
- ! case FLOAT_EXTEND:
- ! return ((mode == DFmode && GET_MODE (XEXP (op, 0)) == SFmode)
- ! || (mode == XFmode && GET_MODE (XEXP (op, 0)) == DFmode)
- ! || (mode == XFmode && GET_MODE (XEXP (op, 0)) == SFmode));
-
- ! default:
- ! return 0;
- ! }
- ! }
-
- ! /* Return 1 if this is a valid shift or rotate operation on a 386.
- ! OP is the expression matched, and MODE is its mode. */
-
- ! int
- ! shift_op (op, mode)
- ! register rtx op;
- ! enum machine_mode mode;
- ! {
- ! rtx operand = XEXP (op, 0);
-
- ! if (mode != VOIDmode && mode != GET_MODE (op))
- ! return 0;
-
- ! if (GET_MODE (operand) != GET_MODE (op)
- ! || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
- ! return 0;
-
- ! return (GET_CODE (op) == ASHIFT
- ! || GET_CODE (op) == ASHIFTRT
- ! || GET_CODE (op) == LSHIFTRT
- ! || GET_CODE (op) == ROTATE
- ! || GET_CODE (op) == ROTATERT);
- ! }
-
- ! /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
- ! MODE is not used. */
-
- ! int
- ! VOIDmode_compare_op (op, mode)
- ! register rtx op;
- ! enum machine_mode mode;
- ! {
- ! return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode;
- ! }
- !
- ! /* Output code to perform a 387 binary operation in INSN, one of PLUS,
- ! MINUS, MULT or DIV. OPERANDS are the insn operands, where operands[3]
- ! is the expression of the binary operation. The output may either be
- ! emitted here, or returned to the caller, like all output_* functions.
-
- ! There is no guarantee that the operands are the same mode, as they
- ! might be within FLOAT or FLOAT_EXTEND expressions. */
-
- ! char *
- ! output_387_binary_op (insn, operands)
- ! rtx insn;
- ! rtx *operands;
- ! {
- ! rtx temp;
- ! char *base_op;
- ! static char buf[100];
-
- ! switch (GET_CODE (operands[3]))
- ! {
- ! case PLUS:
- ! if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- ! || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- ! base_op = "fiadd";
- ! else
- ! base_op = "fadd";
- ! break;
-
- ! case MINUS:
- ! if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- ! || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- ! base_op = "fisub";
- ! else
- ! base_op = "fsub";
- ! break;
-
- ! case MULT:
- ! if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- ! || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- ! base_op = "fimul";
- ! else
- ! base_op = "fmul";
- ! break;
-
- ! case DIV:
- ! if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- ! || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- ! base_op = "fidiv";
- ! else
- ! base_op = "fdiv";
- ! break;
-
- ! default:
- ! abort ();
- ! }
-
- ! strcpy (buf, base_op);
-
- ! switch (GET_CODE (operands[3]))
- {
- ! case MULT:
- ! case PLUS:
- ! if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
- {
- ! temp = operands[2];
- ! operands[2] = operands[1];
- ! operands[1] = temp;
- }
-
- ! if (GET_CODE (operands[2]) == MEM)
- ! return strcat (buf, AS1 (%z2,%2));
-
- ! if (NON_STACK_REG_P (operands[1]))
- {
- ! output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
- ! RET;
- }
- ! else if (NON_STACK_REG_P (operands[2]))
- {
- ! output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
- ! RET;
- }
- !
- ! if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
- ! return strcat (buf, AS2 (p,%2,%0));
- !
- ! if (STACK_TOP_P (operands[0]))
- ! return strcat (buf, AS2 (,%y2,%0));
- ! else
- ! return strcat (buf, AS2 (,%2,%0));
- !
- ! case MINUS:
- ! case DIV:
- ! if (GET_CODE (operands[1]) == MEM)
- ! return strcat (buf, AS1 (r%z1,%1));
- !
- ! if (GET_CODE (operands[2]) == MEM)
- ! return strcat (buf, AS1 (%z2,%2));
- !
- ! if (NON_STACK_REG_P (operands[1]))
- {
- ! output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
- ! RET;
- }
- ! else if (NON_STACK_REG_P (operands[2]))
- {
- ! output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
- ! RET;
- }
- !
- ! if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
- ! abort ();
- !
- ! if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
- ! return strcat (buf, AS2 (rp,%2,%0));
- !
- ! if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- ! return strcat (buf, AS2 (p,%1,%0));
- !
- ! if (STACK_TOP_P (operands[0]))
- {
- ! if (STACK_TOP_P (operands[1]))
- ! return strcat (buf, AS2 (,%y2,%0));
- ! else
- ! return strcat (buf, AS2 (r,%y1,%0));
- }
- + else if (STACK_TOP_P (operands[1]))
- + return strcat (buf, AS2 (,%1,%0));
- + else
- + return strcat (buf, AS2 (r,%2,%0));
-
- ! default:
- ! abort ();
- ! }
- ! }
- !
- ! /* Output code for INSN to convert a float to a signed int. OPERANDS
- ! are the insn operands. The output may be SFmode or DFmode and the
- ! input operand may be SImode or DImode. As a special case, make sure
- ! that the 387 stack top dies if the output mode is DImode, because the
- ! hardware requires this. */
-
- ! char *
- ! output_fix_trunc (insn, operands)
- ! rtx insn;
- ! rtx *operands;
- ! {
- ! int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- ! rtx xops[2];
-
- ! if (! STACK_TOP_P (operands[1]) ||
- ! (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
- ! abort ();
-
- ! xops[0] = GEN_INT (12);
- ! xops[1] = operands[4];
-
- ! output_asm_insn (AS1 (fnstc%W2,%2), operands);
- ! output_asm_insn (AS2 (mov%L2,%2,%4), operands);
- ! output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
- ! output_asm_insn (AS2 (mov%L4,%4,%3), operands);
- ! output_asm_insn (AS1 (fldc%W3,%3), operands);
-
- ! if (NON_STACK_REG_P (operands[0]))
- ! output_to_reg (operands[0], stack_top_dies);
- ! else if (GET_CODE (operands[0]) == MEM)
- ! {
- ! if (stack_top_dies)
- ! output_asm_insn (AS1 (fistp%z0,%0), operands);
- ! else
- ! output_asm_insn (AS1 (fist%z0,%0), operands);
- ! }
- ! else
- ! abort ();
-
- ! return AS1 (fldc%W2,%2);
- ! }
- !
- ! /* Output code for INSN to compare OPERANDS. The two operands might
- ! not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
- ! expression. If the compare is in mode CCFPEQmode, use an opcode that
- ! will not fault if a qNaN is present. */
-
- ! char *
- ! output_float_compare (insn, operands)
- ! rtx insn;
- ! rtx *operands;
- ! {
- ! int stack_top_dies;
- ! rtx body = XVECEXP (PATTERN (insn), 0, 0);
- ! int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
-
- ! /* intel1 */
- ! rtx tmp;
- ! if (! STACK_TOP_P (operands[0]))
- ! {
- ! tmp = operands[0];
- ! operands[0] = operands[1];
- ! operands[1] = tmp;
- ! cc_status.flags |= CC_REVERSED;
- ! }
- !
- ! if (! STACK_TOP_P (operands[0]))
- ! abort ();
-
- ! stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
-
- ! if (STACK_REG_P (operands[1])
- ! && stack_top_dies
- ! && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
- ! && REGNO (operands[1]) != FIRST_STACK_REG)
- ! {
- ! /* If both the top of the 387 stack dies, and the other operand
- ! is also a stack register that dies, then this must be a
- ! `fcompp' float compare */
- !
- ! if (unordered_compare)
- ! output_asm_insn ("fucompp", operands);
- else
- ! output_asm_insn ("fcompp", operands);
- }
- + else
- + {
- + static char buf[100];
- +
- + /* Decide if this is the integer or float compare opcode, or the
- + unordered float compare. */
- +
- + if (unordered_compare)
- + strcpy (buf, "fucom");
- + else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
- + strcpy (buf, "fcom");
- + else
- + strcpy (buf, "ficom");
- +
- + /* Modify the opcode if the 387 stack is to be popped. */
- +
- + if (stack_top_dies)
- + strcat (buf, "p");
- +
- + if (NON_STACK_REG_P (operands[1]))
- + output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
- + else
- + output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
- + }
- +
- + /* Now retrieve the condition code. */
- +
- + return output_fp_cc0_set (insn);
- }
-
- ! /* Output opcodes to transfer the results of FP compare or test INSN
- ! from the FPU to the CPU flags. If TARGET_IEEE_FP, ensure that if the
- ! result of the compare or test is unordered, no comparison operator
- ! succeeds except NE. Return an output template, if any. */
-
- ! char *
- ! output_fp_cc0_set (insn)
- ! rtx insn;
- ! {
- ! rtx xops[3];
- ! rtx unordered_label;
- ! rtx next;
- ! enum rtx_code code;
-
- ! xops[0] = gen_rtx (REG, HImode, 0);
- ! output_asm_insn (AS1 (fnsts%W0,%0), xops);
-
- !
- ! if (! TARGET_IEEE_FP)
- {
- ! /* intel1 */
- ! if (!(cc_status.flags & CC_REVERSED))
- ! {
- ! next = next_cc0_user (insn);
- !
- ! if (GET_CODE (next) == JUMP_INSN
- ! && GET_CODE (PATTERN (next)) == SET
- ! && SET_DEST (PATTERN (next)) == pc_rtx
- ! && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
- ! {
- ! code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
- ! }
- ! else if (GET_CODE (PATTERN (next)) == SET)
- ! {
- ! code = GET_CODE (SET_SRC (PATTERN (next)));
- ! }
- ! else
- ! {
- ! return "sahf";
- ! }
- ! if (code == GT || code == LT || code == EQ || code == NE
- ! || code == LE || code == GE)
- ! { /* We will test eax directly */
- ! cc_status.flags |= CC_TEST_AX;
- ! RET;
- ! }
- ! }
- ! return "sahf";
- ! }
-
- ! next = next_cc0_user (insn);
- ! if (next == NULL_RTX)
- ! abort ();
-
- ! if (GET_CODE (next) == JUMP_INSN
- ! && GET_CODE (PATTERN (next)) == SET
- ! && SET_DEST (PATTERN (next)) == pc_rtx
- ! && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
- ! {
- ! code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
- }
- ! else if (GET_CODE (PATTERN (next)) == SET)
- {
- ! code = GET_CODE (SET_SRC (PATTERN (next)));
- }
- else
- + abort ();
- +
- + xops[0] = gen_rtx (REG, QImode, 0);
- +
- + switch (code)
- {
- ! case GT:
- ! xops[1] = GEN_INT (0x45);
- ! output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- ! /* je label */
- ! break;
- !
- ! case LT:
- ! xops[1] = GEN_INT (0x45);
- ! xops[2] = GEN_INT (0x01);
- ! output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- ! output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- ! /* je label */
- ! break;
- !
- ! case GE:
- ! xops[1] = GEN_INT (0x05);
- ! output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- ! /* je label */
- ! break;
- !
- ! case LE:
- ! xops[1] = GEN_INT (0x45);
- ! xops[2] = GEN_INT (0x40);
- ! output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- ! output_asm_insn (AS1 (dec%B0,%h0), xops);
- ! output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- ! /* jb label */
- ! break;
- !
- ! case EQ:
- ! xops[1] = GEN_INT (0x45);
- ! xops[2] = GEN_INT (0x40);
- ! output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- ! output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- ! /* je label */
- ! break;
- !
- ! case NE:
- ! xops[1] = GEN_INT (0x44);
- ! xops[2] = GEN_INT (0x40);
- ! output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- ! output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
- ! /* jne label */
- ! break;
- !
- ! case GTU:
- ! case LTU:
- ! case GEU:
- ! case LEU:
- ! default:
- ! abort ();
- }
- + RET;
- + }
- +
- + #define MAX_386_STACK_LOCALS 2
- +
- + static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
- +
- + /* Define the structure for the machine field in struct function. */
- + struct machine_function
- + {
- + rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
- + };
- +
- + /* Functions to save and restore i386_stack_locals.
- + These will be called, via pointer variables,
- + from push_function_context and pop_function_context. */
- +
- + void
- + save_386_machine_status (p)
- + struct function *p;
- + {
- + p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals);
- + bcopy (i386_stack_locals, p->machine->i386_stack_locals,
- + sizeof i386_stack_locals);
- }
-
- void
- ! restore_386_machine_status (p)
- ! struct function *p;
- {
- ! bcopy (p->machine->i386_stack_locals, i386_stack_locals,
- ! sizeof i386_stack_locals);
- ! free (p->machine);
- }
-
- ! /* Clear stack slot assignments remembered from previous functions.
- ! This is called from INIT_EXPANDERS once before RTL is emitted for each
- ! function. */
- !
- ! void
- ! clear_386_stack_locals ()
- {
- ! enum machine_mode mode;
- ! int n;
-
- ! for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
- ! mode = (enum machine_mode) ((int) mode + 1))
- ! for (n = 0; n < MAX_386_STACK_LOCALS; n++)
- ! i386_stack_locals[(int) mode][n] = NULL_RTX;
-
- ! /* Arrange to save and restore i386_stack_locals around nested functions. */
- ! save_machine_status = save_386_machine_status;
- ! restore_machine_status = restore_386_machine_status;
- }
-
- ! /* Return a MEM corresponding to a stack slot with mode MODE.
- ! Allocate a new slot if necessary.
-
- ! The RTL for a function can have several slots available: N is
- ! which slot to use. */
- !
- ! rtx
- ! assign_386_stack_local (mode, n)
- ! enum machine_mode mode;
- ! int n;
- {
- ! if (n < 0 || n >= MAX_386_STACK_LOCALS)
- ! abort ();
-
- ! if (i386_stack_locals[(int) mode][n] == NULL_RTX)
- ! {
- ! i386_stack_locals[(int) mode][n]
- ! = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
- ! }
- ! return i386_stack_locals[(int) mode][n];
- ! }
-
-
- ! /* all functions after here added by intel1 */
- ! /* intel1 */
- ! int is_mul(op,mode)
- ! register rtx op;
- ! enum machine_mode mode;
- ! {
- ! return(GET_CODE(op)==MULT);
- }
-
- ! /* intel1 */
- ! int is_div(op,mode)
- register rtx op;
- enum machine_mode mode;
- {
- ! return(GET_CODE(op)==DIV);
- }
-
- ! /* Create a new copy of an rtx.
- ! Recursively copies the operands of the rtx,
- ! except for those few rtx codes that are sharable.
- ! Doesn't share CONST */
-
- ! rtx
- ! copy_all_rtx (orig)
- ! register rtx orig;
- {
- ! register rtx copy;
- ! register int i, j;
- ! register RTX_CODE code;
- ! register char *format_ptr;
-
- ! code = GET_CODE (orig);
- !
- ! switch (code)
- {
- ! case REG:
- ! case QUEUED:
- ! case CONST_INT:
- ! case CONST_DOUBLE:
- ! case SYMBOL_REF:
- ! case CODE_LABEL:
- ! case PC:
- ! case CC0:
- ! case SCRATCH:
- ! /* SCRATCH must be shared because they represent distinct values. */
- ! return orig;
-
- ! #if 0
- ! case CONST:
- ! /* CONST can be shared if it contains a SYMBOL_REF. If it contains
- ! a LABEL_REF, it isn't sharable. */
- ! if (GET_CODE (XEXP (orig, 0)) == PLUS
- ! && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
- ! && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
- ! return orig;
- break;
- + #endif
- + /* A MEM with a constant address is not sharable. The problem is that
- + the constant address may need to be reloaded. If the mem is shared,
- + then reloading one copy of this mem will cause all copies to appear
- + to have been reloaded. */
- + }
- +
- + copy = rtx_alloc (code);
- + PUT_MODE (copy, GET_MODE (orig));
- + copy->in_struct = orig->in_struct;
- + copy->volatil = orig->volatil;
- + copy->unchanging = orig->unchanging;
- + copy->integrated = orig->integrated;
- + /* intel1 */
- + copy->is_spill_rtx = orig->is_spill_rtx;
- +
- + format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
- +
- + for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
- + {
- + switch (*format_ptr++)
- + {
- + case 'e':
- + XEXP (copy, i) = XEXP (orig, i);
- + if (XEXP (orig, i) != NULL)
- + XEXP (copy, i) = copy_rtx (XEXP (orig, i));
- + break;
-
- ! case '0':
- ! case 'u':
- ! XEXP (copy, i) = XEXP (orig, i);
- ! break;
-
- ! case 'E':
- ! case 'V':
- ! XVEC (copy, i) = XVEC (orig, i);
- ! if (XVEC (orig, i) != NULL)
- ! {
- ! XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
- ! for (j = 0; j < XVECLEN (copy, i); j++)
- ! XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
- ! }
- ! break;
-
- ! case 'w':
- ! XWINT (copy, i) = XWINT (orig, i);
- ! break;
- !
- ! case 'i':
- ! XINT (copy, i) = XINT (orig, i);
- ! break;
- !
- ! case 's':
- ! case 'S':
- ! XSTR (copy, i) = XSTR (orig, i);
- ! break;
- !
- ! default:
- ! abort ();
- ! }
- ! }
- ! return copy;
- ! }
- !
- !
- ! /* try to rewrite a memory address to make it valid */
- ! void
- ! rewrite_address (mem_rtx)
- ! rtx mem_rtx;
- ! {
- ! rtx index_rtx, base_rtx, offset_rtx, scale_rtx, ret_rtx;
- ! int scale = 1;
- ! int offset_adjust = 0;
- ! int was_only_offset = 0;
- ! rtx mem_addr = XEXP (mem_rtx, 0);
- ! char *storage = (char *) oballoc (0);
- ! int in_struct = 0;
- ! int is_spill_rtx = 0;
- !
- ! in_struct = MEM_IN_STRUCT_P (mem_rtx);
- ! is_spill_rtx = RTX_IS_SPILL_P (mem_rtx);
- !
- ! if (GET_CODE (mem_addr) == PLUS &&
- ! GET_CODE (XEXP (mem_addr, 1)) == PLUS &&
- ! GET_CODE (XEXP (XEXP (mem_addr, 1), 0)) == REG)
- ! { /* this part is utilized by the combiner */
- ! ret_rtx =
- ! gen_rtx (PLUS, GET_MODE (mem_addr),
- ! gen_rtx (PLUS, GET_MODE (XEXP (mem_addr, 1)),
- ! XEXP (mem_addr, 0),
- ! XEXP (XEXP (mem_addr, 1), 0)),
- ! XEXP (XEXP (mem_addr, 1), 1));
- ! if (memory_address_p (GET_MODE (mem_rtx), ret_rtx))
- ! {
- ! XEXP (mem_rtx, 0) = ret_rtx;
- ! RTX_IS_SPILL_P (ret_rtx) = is_spill_rtx;
- ! return;
- ! }
- ! obfree (storage);
- ! }
- !
- ! /* this part is utilized by loop.c */
- ! /* If the address contains PLUS (reg,const) and this pattern is invalid
- ! in this case - try to rewrite the address to make it valid intel1
- ! */
- ! storage = (char *) oballoc (0);
- ! index_rtx = base_rtx = offset_rtx = NULL;
- ! /* find the base index and offset elements of the memory address */
- ! if (GET_CODE (mem_addr) == PLUS)
- ! {
- ! if (GET_CODE (XEXP (mem_addr, 0)) == REG)
- ! {
- ! if (GET_CODE (XEXP (mem_addr, 1)) == REG)
- ! {
- ! base_rtx = XEXP (mem_addr, 1);
- ! index_rtx = XEXP (mem_addr, 0);
- ! }
- ! else
- ! {
- ! base_rtx = XEXP (mem_addr, 0);
- ! offset_rtx = XEXP (mem_addr, 1);
- ! }
- ! }
- ! else if (GET_CODE (XEXP (mem_addr, 0)) == MULT)
- ! {
- ! index_rtx = XEXP (mem_addr, 0);
- ! if (GET_CODE (XEXP (mem_addr, 1)) == REG)
- ! {
- ! base_rtx = XEXP (mem_addr, 1);
- ! }
- ! else
- ! {
- ! offset_rtx = XEXP (mem_addr, 1);
- ! }
- ! }
- ! else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS)
- ! {
- ! /* intel1 */
- ! if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == PLUS &&
- ! GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == MULT &&
- ! GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 0)) == REG &&
- ! GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 1)) == CONST_INT &&
- ! GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) == CONST_INT &&
- ! GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG &&
- ! GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF)
- ! {
- ! index_rtx = XEXP (XEXP (XEXP (mem_addr, 0), 0), 0);
- ! offset_rtx = XEXP (mem_addr, 1);
- ! base_rtx = XEXP (XEXP (mem_addr, 0), 1);
- ! offset_adjust = INTVAL (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1));
- ! }
- ! else
- ! {
- ! offset_rtx = XEXP (mem_addr, 1);
- ! index_rtx = XEXP (XEXP (mem_addr, 0), 0);
- ! base_rtx = XEXP (XEXP (mem_addr, 0), 1);
- ! }
- ! }
- ! else if (GET_CODE (XEXP (mem_addr, 0)) == CONST_INT)
- ! {
- ! was_only_offset = 1;
- ! index_rtx = NULL;
- ! base_rtx = NULL;
- ! offset_rtx = XEXP (mem_addr, 1);
- ! offset_adjust = INTVAL (XEXP (mem_addr, 0));
- ! if (offset_adjust == 0)
- ! {
- ! XEXP (mem_rtx, 0) = offset_rtx;
- ! RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
- ! return;
- ! }
- ! }
- ! else
- ! {
- ! obfree (storage);
- ! return;
- ! }
- ! }
- ! else if (GET_CODE (mem_addr) == MULT)
- ! {
- ! index_rtx = mem_addr;
- ! }
- ! else
- ! {
- ! obfree (storage);
- ! return;
- ! }
- ! if (index_rtx && GET_CODE (index_rtx) == MULT)
- ! {
- ! if (GET_CODE (XEXP (index_rtx, 1)) != CONST_INT)
- ! {
- ! obfree (storage);
- ! return;
- ! }
- ! scale_rtx = XEXP (index_rtx, 1);
- ! scale = INTVAL (scale_rtx);
- ! index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
- ! }
- ! /* now find which of the elements are invalid and try to fix them */
- ! if (index_rtx && GET_CODE (index_rtx) == CONST_INT && base_rtx == NULL)
- ! {
- ! offset_adjust = INTVAL (index_rtx) * scale;
- ! if (offset_rtx && GET_CODE (offset_rtx) == CONST &&
- ! GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
- ! {
- ! if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
- ! GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
- ! {
- ! offset_rtx = copy_all_rtx (offset_rtx);
- ! XEXP (XEXP (offset_rtx, 0), 1) =
- ! gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
- ! if (!CONSTANT_P (offset_rtx))
- ! {
- ! obfree (storage);
- ! return;
- ! }
- ! }
- ! }
- ! else if (offset_rtx && GET_CODE (offset_rtx) == SYMBOL_REF)
- ! {
- ! offset_rtx =
- ! gen_rtx (CONST, GET_MODE (offset_rtx),
- ! gen_rtx (PLUS, GET_MODE (offset_rtx),
- ! offset_rtx,
- ! gen_rtx (CONST_INT, 0, offset_adjust)));
- ! if (!CONSTANT_P (offset_rtx))
- ! {
- ! obfree (storage);
- ! return;
- ! }
- ! }
- ! else if (offset_rtx && GET_CODE (offset_rtx) == CONST_INT)
- ! {
- ! offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
- ! }
- ! else if (!offset_rtx)
- ! {
- ! offset_rtx = gen_rtx (CONST_INT, 0, 0);
- ! }
- ! RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
- ! XEXP (mem_rtx, 0) = offset_rtx;
- ! return;
- }
- ! if (base_rtx && GET_CODE (base_rtx) == PLUS &&
- ! GET_CODE (XEXP (base_rtx, 0)) == REG &&
- ! GET_CODE (XEXP (base_rtx, 1)) == CONST_INT)
- {
- ! offset_adjust += INTVAL (XEXP (base_rtx, 1));
- ! base_rtx = copy_all_rtx (XEXP (base_rtx, 0));
- ! }
- ! else if (base_rtx && GET_CODE (base_rtx) == CONST_INT)
- ! {
- ! offset_adjust += INTVAL (base_rtx);
- ! base_rtx = NULL;
- ! }
- ! if (index_rtx && GET_CODE (index_rtx) == PLUS &&
- ! GET_CODE (XEXP (index_rtx, 0)) == REG &&
- ! GET_CODE (XEXP (index_rtx, 1)) == CONST_INT)
- ! {
- ! offset_adjust += INTVAL (XEXP (index_rtx, 1)) * scale;
- ! index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
- ! }
- ! if (index_rtx)
- ! {
- ! if (!LEGITIMATE_INDEX_P (index_rtx)
- ! && !(index_rtx == stack_pointer_rtx && scale == 1 && base_rtx == NULL))
- {
- ! obfree (storage);
- ! return;
- }
- ! }
- ! if (base_rtx)
- ! {
- ! if (!LEGITIMATE_INDEX_P (base_rtx) && GET_CODE (base_rtx) != REG)
- {
- ! obfree (storage);
- ! return;
- }
- ! }
- ! if (offset_adjust != 0)
- ! {
- ! if (offset_rtx)
- {
- ! if (GET_CODE (offset_rtx) == CONST &&
- ! GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
- ! {
- ! if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
- ! GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
- ! {
- ! offset_rtx = copy_all_rtx (offset_rtx);
- ! XEXP (XEXP (offset_rtx, 0), 1) =
- ! gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
- ! if (!CONSTANT_P (offset_rtx))
- ! {
- ! obfree (storage);
- ! return;
- ! }
- ! }
- ! }
- ! else if (GET_CODE (offset_rtx) == SYMBOL_REF)
- ! {
- ! offset_rtx =
- ! gen_rtx (CONST, GET_MODE (offset_rtx),
- ! gen_rtx (PLUS, GET_MODE (offset_rtx),
- ! offset_rtx,
- ! gen_rtx (CONST_INT, 0, offset_adjust)));
- ! if (!CONSTANT_P (offset_rtx))
- ! {
- ! obfree (storage);
- ! return;
- ! }
- ! }
- ! else if (GET_CODE (offset_rtx) == CONST_INT)
- ! {
- ! offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
- ! }
- ! else
- ! {
- ! obfree (storage);
- ! return;
- ! }
- }
- else
- {
- ! offset_rtx = gen_rtx (CONST_INT, 0, offset_adjust);
- }
- ! if (index_rtx)
- {
- ! if (base_rtx)
- ! {
- ! if (scale != 1)
- ! {
- ! if (GET_CODE (offset_rtx) == CONST_INT &&
- ! INTVAL (offset_rtx) == 0)
- ! {
- ! ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx),
- ! gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
- ! scale_rtx),
- ! base_rtx);
- ! }
- ! else
- ! {
- ! ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
- ! gen_rtx (PLUS, GET_MODE (base_rtx),
- ! gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
- ! scale_rtx),
- ! base_rtx),
- ! offset_rtx);
- ! }
- ! }
- ! else
- ! {
- ! if (GET_CODE (offset_rtx) == CONST_INT &&
- ! INTVAL (offset_rtx) == 0)
- ! {
- ! ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, base_rtx);
- ! }
- ! else
- ! {
- ! ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
- ! gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx,
- ! base_rtx),
- ! offset_rtx);
- ! }
- ! }
- ! }
- ! else
- ! {
- ! if (scale != 1)
- ! {
- ! if (GET_CODE (offset_rtx) == CONST_INT &&
- ! INTVAL (offset_rtx) == 0)
- ! {
- ! ret_rtx = gen_rtx (MULT, GET_MODE (index_rtx), index_rtx, scale_rtx);
- ! }
- ! else
- ! {
- ! ret_rtx =
- ! gen_rtx (PLUS, GET_MODE (offset_rtx),
- ! gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
- ! scale_rtx),
- ! offset_rtx);
- ! }
- ! }
- ! else
- ! {
- ! if (GET_CODE (offset_rtx) == CONST_INT &&
- ! INTVAL (offset_rtx) == 0)
- ! {
- ! ret_rtx = index_rtx;
- ! }
- ! else
- ! {
- ! ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, offset_rtx);
- ! }
- ! }
- ! }
- }
- ! else
- {
- ! if (base_rtx)
- ! {
- ! if (GET_CODE (offset_rtx) == CONST_INT &&
- ! INTVAL (offset_rtx) == 0)
- ! {
- ! ret_rtx = base_rtx;
- ! }
- ! else
- ! {
- ! ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), base_rtx, offset_rtx);
- ! }
- ! }
- ! else if (was_only_offset)
- ! {
- ! ret_rtx = offset_rtx;
- ! }
- else
- ! {
- ! obfree (storage);
- ! return;
- ! }
- }
- ! XEXP (mem_rtx, 0) = ret_rtx;
- ! RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
- ! return;
- ! }
- ! else
- ! {
- ! obfree (storage);
- ! return;
- }
- }
-
- ! /* return 1 if the first insn to set cc before insn also sets the register
- ! reg_rtx - otherwise return 0
- ! */
- ! int
- ! last_to_set_cc (reg_rtx, insn)
- ! rtx reg_rtx, insn;
- {
- ! rtx prev_insn = PREV_INSN (insn);
-
- ! while (prev_insn)
- {
- ! if (GET_CODE (prev_insn) == NOTE)
- ! {
- ! ;
- ! }
- ! else if (GET_CODE (prev_insn) == INSN)
- ! {
- ! if (GET_CODE (PATTERN (prev_insn)) != SET)
- ! {
- ! return (0);
- ! }
- ! if (rtx_equal_p (SET_DEST (PATTERN (prev_insn)), reg_rtx))
- ! {
- ! if (sets_condition_code (SET_SRC (PATTERN (prev_insn))))
- ! {
- ! return (1);
- ! }
- ! else
- ! {
- ! return (0);
- ! }
- ! }
- ! else if (!doesnt_set_condition_code (SET_SRC (PATTERN (prev_insn))))
- ! {
- ! return (0);
- ! }
- ! }
- else
- ! {
- ! return (0);
- ! }
- ! prev_insn = PREV_INSN (prev_insn);
- }
- ! return (0);
- }
-
- ! int
- ! doesnt_set_condition_code (pat)
- ! rtx pat;
- {
- ! switch (GET_CODE (pat))
- {
- ! case MEM:
- ! case REG:
- ! return (1);
-
- ! default:
- ! return (0);
-
- ! }
- }
-
- ! int
- ! sets_condition_code (pat)
- ! rtx pat;
- {
- ! switch (GET_CODE (pat))
- ! {
- ! case PLUS:
- ! case MINUS:
- ! case AND:
- ! case IOR:
- ! case XOR:
- ! case NOT:
- ! case NEG:
- ! case MULT:
- ! case DIV:
- ! case MOD:
- ! case UDIV:
- ! case UMOD:
- ! return (1);
-
- ! default:
- ! return (0);
-
- ! }
- ! }
-
-
- ! /* intel1 */
- ! int
- ! str_immediate_operand (op, mode)
- ! register rtx op;
- ! enum machine_mode mode;
- ! {
- ! if (GET_CODE (op) == CONST_INT && INTVAL (op) <= 32 && INTVAL (op) >= 0)
- {
- ! return (1);
- }
- ! return (0);
- ! }
-
- ! /* intel1 */
- ! void
- ! override_options ()
- ! {
- ! register int i, start;
- ! register int regno;
- ! register enum machine_mode mode;
- ! char *p;
- ! #if 0
- ! int blend = 0;
- ! #endif
-
- ! /* only one `-mcpu' allowed */
- ! if (TARGET_X && (TARGET_X != TARGET_386) && (TARGET_X != TARGET_486) && (TARGET_X != TARGET_PENTIUM))
- ! fatal ("multilple `-mcpu' definitions .\n");
- !
- ! /* if `-mcpu' use it, otherwise take default */
- ! target_flags |= USE_CPU;
- !
- ! if (TARGET_PENTIUM)
- ! x86_cpu = PROCESSOR_PENTIUM;
- ! else if (TARGET_486)
- ! x86_cpu = PROCESSOR_486;
- ! else if (TARGET_386)
- ! x86_cpu = PROCESSOR_386;
- ! else /* no processor type ? */
- ! fatal ("no processor type.\n");
- !
- ! #if 0 /* what happens if we have few -mcpu's, I don't think it's needed */
- ! /* Identify the processor type */
- ! if (!(TARGET_PENTIUM) && !(TARGET_486) && !(TARGET_386))
- ! {
- ! x86_cpu = PROCESSOR_PENTIUM;
- ! target_flags |= (TARGET_486_SWITCH);
- ! blend = 1;
- ! }
- !
- ! else
- {
- ! x86_cpu = PROCESSOR_DEFAULT;
- ! if (TARGET_PENTIUM)
- ! {
- ! x86_cpu = PROCESSOR_PENTIUM;
- ! }
- ! if (TARGET_486)
- ! {
- ! if (x86_cpu != PROCESSOR_DEFAULT)
- ! {
- ! error ("conflicting -mX86 : using blend");
- ! blend = 1;
- ! x86_cpu = PROCESSOR_PENTIUM;
- ! target_flags &= ~(TARGET_386_SWITCH);
- ! target_flags &= ~(TARGET_PENTIUM_SWITCH);
- ! }
- ! else
- ! {
- ! x86_cpu = PROCESSOR_486;
- ! }
- ! }
- ! if (TARGET_386)
- ! {
- ! if (x86_cpu != PROCESSOR_DEFAULT)
- ! {
- ! error ("conflicting -mX86 : using blend");
- ! blend = 1;
- ! x86_cpu = PROCESSOR_486;
- ! target_flags &= ~(TARGET_386_SWITCH);
- ! target_flags &= ~(TARGET_PENTIUM_SWITCH);
- ! target_flags |= (TARGET_486_SWITCH);
- ! }
- ! else
- ! {
- ! x86_cpu = PROCESSOR_386;
- ! }
- ! }
-
-
- ! }
- ! #endif
- ! if (opt_level >= 4)
- ! {
- ! if (TARGET_486)
- ! {
- ! if (opt_level == 4
- ! && !flag_no_interleave_stack_non_stack)
- ! {
- ! flag_interleave_stack_non_stack = 1;
- ! flag_schedule_insns = 1;
- ! }
- ! }
- ! #if 0
- ! if(TARGET_BLEND)
- ! {
- ! if (!flag_no_risc)
- ! flag_risc = 1;
- ! if (!flag_no_risc_const)
- ! flag_risc_const = 1;
- ! if (!flag_no_recombine)
- ! flag_recombine = 1;
- ! }
- ! #endif
- ! if (TARGET_PENTIUM)
- ! {
- ! if (!flag_no_risc)
- ! flag_risc = 1;
- ! if (!flag_no_risc_const)
- ! flag_risc_const = 1;
- ! /*if (!flag_no_recombine)
- ! flag_recombine = 1;*/
- ! if (opt_level == 4
- ! && !flag_no_schedule_stack_reg_insns)
- ! {
- ! flag_schedule_stack_reg_insns = 1;
- ! flag_schedule_insns = 1;
- ! }
- ! if (opt_level == 4
- ! && !flag_no_interleave_stack_non_stack)
- ! {
- ! flag_interleave_stack_non_stack = 1;
- ! flag_schedule_insns = 1;
- ! }
- ! }
- ! }
- ! }
-
-
-
-
- ! optimization_options (level)
- ! int level;
- ! {
- ! opt_level = level;
- ! if (level > 0)
- ! {
- ! flag_opt_reg_use = 1;
- ! flag_reduce_index_givs = 1;
- }
- ! if (level >= 2)
- ! {
- ! #ifdef INSN_SCHEDULING
- ! flag_schedule_insns = 0;
- ! flag_schedule_insns_after_reload = 0;
- ! #endif
- ! }
- ! if (level >= 3)
- ! {
- ! flag_inline_functions = 1;
- ! flag_jump_back = 1;
- ! flag_copy_prop = 1;
- ! flag_compare_elim = 1;
- ! flag_sftwr_pipe = 1;
- ! flag_omit_frame_pointer = 1;
- ! /*flag_reg_reg_copy_opt = 1; */
- ! flag_opt_reg_stack = 1;
- ! /*flag_loop_after_global = 1; */
- ! flag_peep_spills = 1;
- ! flag_replace_stack_mem = 1;
- ! flag_opt_jumps_out = 1;
- ! flag_replace_mem = 1;
- ! flag_correct_cse_mistakes = 1;
- ! flag_push_load_into_loop = 1;
- ! flag_replace_reload_regs = 1;
- ! flag_sign_extension_elim = 1;
- ! flag_lift_stores = 1;
- ! flag_runtime_lift_stores = 1;
- ! }
- ! if (level >= 4)
- ! {
- ! #ifdef INSN_SCHEDULING
- ! flag_schedule_insns_after_reload = 1;
- ! flag_swap_for_agi = 1;
- ! if (TARGET_PENTIUM)
- ! {
- ! /*flag_risc = 1; */
- ! flag_risc_const = 1;
- ! /*flag_recombine = 1;*/
- ! if (level == 4)
- ! {
- ! flag_schedule_stack_reg_insns = 1;
- ! flag_schedule_insns = 1;
- ! }
- ! }
- ! #endif
- ! }
- ! if (level >= 5)
- ! {
- ! #ifdef INSN_SCHEDULING
- ! flag_schedule_insns = 1;
- ! #endif
- ! }
- ! if (flag_no_risc)
- ! flag_risc = 0;
- ! if (flag_no_risc_const)
- ! flag_risc_const = 0;
- ! if (flag_no_recombine)
- ! flag_recombine = 0;
- ! if (flag_no_risc_mem_dest)
- ! flag_risc_mem_dest = 0;
- }
-
- ! /* intel1 */
-
- ! int
- ! is_fp_insn (insn)
- ! rtx insn;
- {
- ! if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
- ! && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
- ! || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode))
- ! {
- ! return (1);
- ! }
- ! return (0);
- ! }
-
-
- ! /*
- ! Return 1 if the mode of the SET_DEST of insn is floating point
- ! and it is not an fld or a move from memory to memory.
- ! Otherwise return 0
- ! */
- ! int
- ! is_fp_dest (insn)
- ! rtx insn;
- {
- ! if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
- ! && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
- ! || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode)
- ! && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- ! && REGNO (SET_DEST (PATTERN (insn))) >= FIRST_FLOAT_REG
- ! && GET_CODE (SET_SRC (insn)) != MEM
- ! )
- ! {
- ! return (1);
- ! }
- ! return (0);
- }
-
- ! /*
- ! Return 1 if the mode of the SET_DEST floating point and is memory
- ! and the source is a register.
- ! */
- ! int
- ! is_fp_store (insn)
- ! rtx insn;
- {
- ! if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
- ! && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
- ! || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode)
- ! && GET_CODE (SET_DEST (PATTERN (insn))) == MEM
- ! && GET_CODE (SET_SRC (PATTERN (insn))) == REG
- ! )
- ! {
- ! return (1);
- ! }
- ! return (0);
- }
-
-
- ! /*
- ! Return 1 if dep_insn sets a register which insn uses as a base
- ! or index to reference memory.
- ! otherwise return 0
- ! */
- ! int
- ! agi_dependent (insn, dep_insn)
- ! rtx insn, dep_insn;
- {
- ! if (GET_CODE (dep_insn) == INSN && GET_CODE (PATTERN (dep_insn)) == SET
- ! && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG)
- ! {
- ! return (reg_mentioned_in_mem (SET_DEST (PATTERN (dep_insn)), insn));
- ! }
- ! if (GET_CODE (dep_insn) == INSN && GET_CODE (PATTERN (dep_insn)) == SET
- ! && GET_CODE (SET_DEST (PATTERN (dep_insn))) == MEM
- ! && push_operand (SET_DEST (PATTERN (dep_insn)),
- ! GET_MODE (SET_DEST (PATTERN (dep_insn))))
- ! )
- ! {
- ! return (reg_mentioned_in_mem (stack_pointer_rtx, insn));
- ! }
- !
- ! return (0);
- ! }
-
- ! /*
- ! Return 1 if reg is used in rtl as a base or index for a memory ref
- ! otherwise return 0.
- ! */
- ! int
- ! reg_mentioned_in_mem (reg, rtl)
- ! rtx reg, rtl;
- ! {
- ! register char *fmt;
- ! register int i;
- ! register enum rtx_code code;
-
- ! if (rtl == NULL)
- ! return (0);
-
- ! code = GET_CODE (rtl);
-
- ! switch (code)
- ! {
- ! case HIGH:
- ! case CONST_INT:
- ! case CONST:
- ! case CONST_DOUBLE:
- ! case SYMBOL_REF:
- ! case LABEL_REF:
- ! case PC:
- ! case CC0:
- ! case SUBREG:
- ! return (0);
-
-
- ! }
-
- ! if (code == MEM && reg_mentioned_p (reg, rtl))
- ! {
- ! return (1);
- ! }
- !
- ! fmt = GET_RTX_FORMAT (code);
- !
- ! for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- ! {
- ! if (fmt[i] == 'E')
- ! {
- ! register int j;
- ! for (j = XVECLEN (rtl, i) - 1; j >= 0; j--)
- ! if (reg_mentioned_in_mem (reg, XVECEXP (rtl, i, j)))
- ! return 1;
- ! }
- ! else if (fmt[i] == 'e'
- ! && reg_mentioned_in_mem (reg, XEXP (rtl, i)))
- ! return 1;
- ! }
- ! return (0);
- }
- +
- diff -rNci gcc-2.7.2/config/i386/i386.h gcc-2.7.2p/config/i386/i386.h
- *** gcc-2.7.2/config/i386/i386.h Fri Sep 22 22:42:57 1995
- --- gcc-2.7.2p/config/i386/i386.h Tue Jan 23 10:31:11 1996
- ***************
- *** 2,7 ****
- --- 2,10 ----
- (386, 486, Pentium).
- Copyright (C) 1988, 1992, 1994, 1995 Free Software Foundation, Inc.
-
- + Pentium cpu support and other enhancements by Tevi Devor Intel Corp.
- + (tevi@iil.intel.com).
- +
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- ***************
- *** 56,179 ****
- /* Run-time compilation parameters selecting different hardware subsets. */
-
- extern int target_flags;
-
- /* Macros used in the machine description to test the flags. */
-
- /* configure can arrange to make this 2, to force a 486. */
- #ifndef TARGET_CPU_DEFAULT
- ! #define TARGET_CPU_DEFAULT 0
- #endif
-
- ! /* Masks for the -m switches */
- ! #define MASK_80387 000000000001 /* Hardware floating point */
- ! #define MASK_486 000000000002 /* 80486 specific */
- ! #define MASK_NOTUSED1 000000000004 /* bit not currently used */
- ! #define MASK_RTD 000000000010 /* Use ret that pops args */
- ! #define MASK_ALIGN_DOUBLE 000000000020 /* align doubles to 2 word boundary */
- ! #define MASK_SVR3_SHLIB 000000000040 /* Uninit locals into bss */
- ! #define MASK_IEEE_FP 000000000100 /* IEEE fp comparisons */
- ! #define MASK_FLOAT_RETURNS 000000000200 /* Return float in st(0) */
- ! #define MASK_NO_FANCY_MATH_387 000000000400 /* Disable sin, cos, sqrt */
- !
- ! /* Temporary codegen switches */
- ! #define MASK_DEBUG_ADDR 000001000000 /* Debug GO_IF_LEGITIMATE_ADDRESS */
- ! #define MASK_NO_WIDE_MULTIPLY 000002000000 /* Disable 32x32->64 multiplies */
- ! #define MASK_NO_MOVE 000004000000 /* Don't generate mem->mem */
- ! #define MASK_DEBUG_ARG 000010000000 /* Debug function_arg */
- !
- ! /* Use the floating point instructions */
- ! #define TARGET_80387 (target_flags & MASK_80387)
- !
- /* Compile using ret insn that pops args.
- This will not work unless you use prototypes at least
- for all functions that can take varying numbers of args. */
- ! #define TARGET_RTD (target_flags & MASK_RTD)
-
- /* Align doubles to a two word boundary. This breaks compatibility with
- the published ABI's for structures containing doubles, but produces
- faster code on the pentium. */
- ! #define TARGET_ALIGN_DOUBLE (target_flags & MASK_ALIGN_DOUBLE)
-
- /* Put uninitialized locals into bss, not data.
- Meaningful only on svr3. */
- ! #define TARGET_SVR3_SHLIB (target_flags & MASK_SVR3_SHLIB)
-
- /* Use IEEE floating point comparisons. These handle correctly the cases
- where the result of a comparison is unordered. Normally SIGFPE is
- generated in such cases, in which case this isn't needed. */
- ! #define TARGET_IEEE_FP (target_flags & MASK_IEEE_FP)
-
- /* Functions that return a floating point value may return that value
- in the 387 FPU or in 386 integer registers. If set, this flag causes
- the 387 to be used, which is compatible with most calling conventions. */
- ! #define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & MASK_FLOAT_RETURNS)
- !
- ! /* Disable generation of FP sin, cos and sqrt operations for 387.
- ! This is because FreeBSD lacks these in the math-emulator-code */
- ! #define TARGET_NO_FANCY_MATH_387 (target_flags & MASK_NO_FANCY_MATH_387)
- !
- ! /* Temporary switches for tuning code generation */
- !
- ! /* Disable 32x32->64 bit multiplies that are used for long long multiplies
- ! and division by constants, but sometimes cause reload problems. */
- ! #define TARGET_NO_WIDE_MULTIPLY (target_flags & MASK_NO_WIDE_MULTIPLY)
- ! #define TARGET_WIDE_MULTIPLY (!TARGET_NO_WIDE_MULTIPLY)
- !
- ! /* Debug GO_IF_LEGITIMATE_ADDRESS */
- ! #define TARGET_DEBUG_ADDR (target_flags & MASK_DEBUG_ADDR)
-
- /* Debug FUNCTION_ARG macros */
- ! #define TARGET_DEBUG_ARG (target_flags & MASK_DEBUG_ARG)
-
- ! /* Hack macros for tuning code generation */
- ! #define TARGET_MOVE ((target_flags & MASK_NO_MOVE) == 0) /* Don't generate memory->memory */
-
- ! /* Specific hardware switches */
- ! #define TARGET_486 (target_flags & MASK_486) /* 80486DX, 80486SX, 80486DX[24] */
- ! #define TARGET_386 (!TARGET_486) /* 80386 */
- !
- ! #define TARGET_SWITCHES \
- ! { { "80387", MASK_80387 }, \
- ! { "no-80387", -MASK_80387 }, \
- ! { "hard-float", MASK_80387 }, \
- ! { "soft-float", -MASK_80387 }, \
- ! { "no-soft-float", MASK_80387 }, \
- ! { "386", -MASK_486 }, \
- ! { "no-386", MASK_486 }, \
- ! { "486", MASK_486 }, \
- ! { "no-486", -MASK_486 }, \
- ! { "rtd", MASK_RTD }, \
- ! { "no-rtd", -MASK_RTD }, \
- ! { "align-double", MASK_ALIGN_DOUBLE }, \
- ! { "no-align-double", -MASK_ALIGN_DOUBLE }, \
- ! { "svr3-shlib", MASK_SVR3_SHLIB }, \
- ! { "no-svr3-shlib", -MASK_SVR3_SHLIB }, \
- ! { "ieee-fp", MASK_IEEE_FP }, \
- ! { "no-ieee-fp", -MASK_IEEE_FP }, \
- ! { "fp-ret-in-387", MASK_FLOAT_RETURNS }, \
- ! { "no-fp-ret-in-387", -MASK_FLOAT_RETURNS }, \
- ! { "no-fancy-math-387", MASK_NO_FANCY_MATH_387 }, \
- ! { "fancy-math-387", -MASK_NO_FANCY_MATH_387 }, \
- ! { "no-wide-multiply", MASK_NO_WIDE_MULTIPLY }, \
- ! { "wide-multiply", -MASK_NO_WIDE_MULTIPLY }, \
- ! { "debug-addr", MASK_DEBUG_ADDR }, \
- ! { "no-debug-addr", -MASK_DEBUG_ADDR }, \
- ! { "move", -MASK_NO_MOVE }, \
- ! { "no-move", MASK_NO_MOVE }, \
- ! { "debug-arg", MASK_DEBUG_ARG }, \
- ! { "no-debug-arg", -MASK_DEBUG_ARG }, \
- ! SUBTARGET_SWITCHES \
- ! { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
- !
- ! /* This macro is similar to `TARGET_SWITCHES' but defines names of
- ! command options that have values. Its definition is an
- ! initializer with a subgrouping for each command option.
- !
- ! Each subgrouping contains a string constant, that defines the
- ! fixed part of the option name, and the address of a variable. The
- ! variable, type `char *', is set to the variable part of the given
- ! option if the fixed part matches. The actual option name is made
- ! by appending `-m' to the specified name. */
- #define TARGET_OPTIONS \
- { { "reg-alloc=", &i386_reg_alloc_order }, \
- { "regparm=", &i386_regparm_string }, \
- --- 59,196 ----
- /* Run-time compilation parameters selecting different hardware subsets. */
-
- extern int target_flags;
- + /* Which processor to schedule for. intel1 */
- +
- + enum processor_type {
- + PROCESSOR_DEFAULT,
- + PROCESSOR_386,
- + PROCESSOR_486,
- + PROCESSOR_PENTIUM
- + };
- + extern enum processor_type x86_cpu; /* which cpu are we scheduling for */
- +
- + /* intel1 */
- + #define REDUCE_INDEX (TARGET_486 || TARGET_PENTIUM)
- + #define SAVE_ON_REGS 1
- + #define MAX_DEST_ADDR_GIVS 5
- + #define PREFER_JUMP_NOT_TAKEN 1
- + #define PREFER_CONST_IN_REG 1
- + #define IGNORE_NON_DATA_DEP 1
- + #define STORE_NOT_SET_CC0 1
- + #define NO_CROSS_JUMP_ON_LOOP_ENTRY 1
- + #define AGI 1
- + /* #define SPILL1 */
- + #define EXPENSIVE_OPS(x) \
- + ( GET_CODE(x)==MULT ? \
- + ((GET_CODE (XEXP (x, 1)) == CONST_INT && \
- + exact_log2 (INTVAL (XEXP (x, 1))) >= 0) ? 0 : 1) : \
- + (GET_CODE(x)==DIV || GET_CODE(x)==UDIV || \
- + GET_CODE(x)==MOD || GET_CODE(x)==UMOD ))
- +
- + #define NO_STACK_REG_REORDER (!TARGET_PENTIUM)
- +
- + #define STACK_REG_REORDER \
- + ((TARGET_PENTIUM) && reload_completed == 0 && flag_schedule_stack_reg_insns)
- +
- + #define STACK_NON_STACK_INTERLEAVE \
- + (reload_completed == 0 && flag_interleave_stack_non_stack)
- +
- + #define IS_RISC_MODE(mode) (((mode) == QImode || (mode) == SImode))
- +
- + /* Number of extra pseudo registers we allocate for so that reg-stack
- + can replace fld's and fstps with movs
- + */
- + #define SPARE_REGS 5
- + #define OVERRIDE_OPTIONS override_options()
- +
-
- /* Macros used in the machine description to test the flags. */
-
- /* configure can arrange to make this 2, to force a 486. */
- #ifndef TARGET_CPU_DEFAULT
- ! #define TARGET_CPU_DEFAULT TARGET_PENTIUM_SWITCH
- #endif
-
- ! /* Compile 80387 insns for floating point (not library calls). */
- ! #define TARGET_80387 (target_flags & 1)
- /* Compile using ret insn that pops args.
- This will not work unless you use prototypes at least
- for all functions that can take varying numbers of args. */
- ! #define TARGET_RTD (target_flags & 8)
-
- /* Align doubles to a two word boundary. This breaks compatibility with
- the published ABI's for structures containing doubles, but produces
- faster code on the pentium. */
- ! #define TARGET_ALIGN_DOUBLE (target_flags & 020)
-
- /* Put uninitialized locals into bss, not data.
- Meaningful only on svr3. */
- ! #define TARGET_SVR3_SHLIB (target_flags & 040)
-
- /* Use IEEE floating point comparisons. These handle correctly the cases
- where the result of a comparison is unordered. Normally SIGFPE is
- generated in such cases, in which case this isn't needed. */
- ! #define TARGET_IEEE_FP (target_flags & 0100)
-
- /* Functions that return a floating point value may return that value
- in the 387 FPU or in 386 integer registers. If set, this flag causes
- the 387 to be used, which is compatible with most calling conventions. */
- ! #define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & 0200)
-
- /* Debug FUNCTION_ARG macros */
- ! #define TARGET_DEBUG_ARG (target_flags & 000010000000)
- !
- ! /* Macro to define tables used to set the flags.
- ! This is a list in braces of pairs in braces,
- ! each pair being { "NAME", VALUE }
- ! where VALUE is the bits to set or minus the bits to clear.
- ! An empty string NAME is used to identify the default VALUE. */
- !
- ! /* intel1 */
- ! #define TARGET_486_SWITCH 2
- ! #define TARGET_486 (target_flags & TARGET_486_SWITCH)
- ! /* Compile code for a Pentium. intel1 */
- ! #define TARGET_PENTIUM_SWITCH 4
- ! #define TARGET_PENTIUM (target_flags & TARGET_PENTIUM_SWITCH)
- ! /* Compile code for an i386. intel1 */
- ! #define TARGET_386_SWITCH 0400
- ! #define TARGET_386 (target_flags & TARGET_386_SWITCH)
- ! /* Compile code for a Blend. intel1 */
- ! #define TARGET_BLEND_SWITCH 02000
- ! #define TARGET_BLEND (target_flags & TARGET_BLEND_SWITCH)
- !
- ! #define TARGET_X ((TARGET_386) | (TARGET_486) | (TARGET_PENTIUM))
- ! #define USE_CPU ((TARGET_X) ? (TARGET_X) : TARGET_CPU_DEFAULT)
- !
- ! #define TARGET_SWITCHES \
- ! { { "80387", 1}, \
- ! { "no-80387", -1}, \
- ! { "soft-float", -1}, \
- ! { "no-soft-float", 1}, \
- ! { "486", 2}, \
- ! { "no-486", -2}, \
- ! { "386", 0400}, \
- ! { "pentium", 4}, \
- ! { "blend", 02000}, \
- ! { "rtd", 8}, \
- ! { "no-rtd", -8}, \
- ! { "align-double", 020}, \
- ! { "no-align-double", -020}, \
- ! { "svr3-shlib", 040}, \
- ! { "no-svr3-shlib", -040}, \
- ! { "ieee-fp", 0100}, \
- ! { "no-ieee-fp", -0100}, \
- ! { "fp-ret-in-387", 0200}, \
- ! { "no-fp-ret-in-387", -0200}, \
- ! { "debug-addr", 000010000000 }, \
- ! { "no-debug-addr", -000010000000}, \
- ! SUBTARGET_SWITCHES \
- ! { "", TARGET_DEFAULT }}
-
- ! /* This is meant to be redefined in the host dependent files */
- ! #define SUBTARGET_SWITCHES
-
- !
- #define TARGET_OPTIONS \
- { { "reg-alloc=", &i386_reg_alloc_order }, \
- { "regparm=", &i386_regparm_string }, \
- ***************
- *** 183,215 ****
- SUBTARGET_OPTIONS \
- }
-
- ! /* Sometimes certain combinations of command options do not make
- ! sense on a particular target machine. You can define a macro
- ! `OVERRIDE_OPTIONS' to take account of this. This macro, if
- ! defined, is executed once just after all the command options have
- ! been parsed.
-
- ! Don't use this macro to turn on various extra optimizations for
- ! `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
-
- ! #define OVERRIDE_OPTIONS override_options ()
-
- - /* These are meant to be redefined in the host dependent files */
- - #define SUBTARGET_SWITCHES
- - #define SUBTARGET_OPTIONS
-
- !
- /* target machine storage layout */
-
- /* Define for XFmode extended real floating point support.
- This will automatically cause REAL_ARITHMETIC to be defined. */
- #define LONG_DOUBLE_TYPE_SIZE 96
- !
- /* Define if you don't want extended real, but do want to use the
- software floating point emulator for REAL_ARITHMETIC and
- decimal <-> binary conversion. */
- /* #define REAL_ARITHMETIC */
-
- /* Define this if most significant byte of a word is the lowest numbered. */
- /* That is true on the 80386. */
-
- --- 200,231 ----
- SUBTARGET_OPTIONS \
- }
-
- ! #define SUBTARGET_OPTIONS
- ! /* intel1 */
-
- ! #define SUB_TARGET_STRING \
- ! (TARGET_PENTIUM ? "Pentium" : (TARGET_386 ? "Intel386" : "Intel486"))
-
- ! #define SUB_TARGET_VERSION fprintf (stderr, " [%s cpu] ", SUB_TARGET_STRING)
-
-
- ! /* Define this to change the optimizations performed by default. */
- !
- ! #define OPTIMIZATION_OPTIONS(LEVEL) \
- ! optimization_options(LEVEL)
- !
- /* target machine storage layout */
-
- /* Define for XFmode extended real floating point support.
- This will automatically cause REAL_ARITHMETIC to be defined. */
- #define LONG_DOUBLE_TYPE_SIZE 96
- !
- /* Define if you don't want extended real, but do want to use the
- software floating point emulator for REAL_ARITHMETIC and
- decimal <-> binary conversion. */
- /* #define REAL_ARITHMETIC */
-
- +
- /* Define this if most significant byte of a word is the lowest numbered. */
- /* That is true on the 80386. */
-
- ***************
- *** 265,270 ****
- --- 281,289 ----
- aligned on 64 bit boundaries. */
- #define BIGGEST_ALIGNMENT (TARGET_ALIGN_DOUBLE ? 64 : 32)
-
- + /* intel1 - align DFmode constants and nonaggregates */
- + #define ALIGN_DFmode (!TARGET_386)
- +
- /* Set this non-zero if move instructions will actually fail to work
- when given unaligned data. */
- #define STRICT_ALIGNMENT 0
- ***************
- *** 292,297 ****
- --- 311,318 ----
- for details. */
-
- #define STACK_REGS
- + /* intel1 */
- + #define IS_STACK_MODE(mode) (mode==DFmode || mode==SFmode)
-
- /* Number of actual hardware registers.
- The hardware registers are assigned numbers for the compiler
- ***************
- *** 329,372 ****
- /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
- { 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
-
- - /* Order in which to allocate registers. Each register must be
- - listed once, even those in FIXED_REGISTERS. List frame pointer
- - late and fixed registers last. Note that, in general, we prefer
- - registers listed in CALL_USED_REGISTERS, keeping the others
- - available for storage of persistent values.
- -
- - Three different versions of REG_ALLOC_ORDER have been tried:
- -
- - If the order is edx, ecx, eax, ... it produces a slightly faster compiler,
- - but slower code on simple functions returning values in eax.
- -
- - If the order is eax, ecx, edx, ... it causes reload to abort when compiling
- - perl 4.036 due to not being able to create a DImode register (to hold a 2
- - word union).
- -
- - If the order is eax, edx, ecx, ... it produces better code for simple
- - functions, and a slightly slower compiler. Users complained about the code
- - generated by allocating edx first, so restore the 'natural' order of things. */
- -
- - #define REG_ALLOC_ORDER \
- - /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
- - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
- -
- - /* A C statement (sans semicolon) to choose the order in which to
- - allocate hard registers for pseudo-registers local to a basic
- - block.
- -
- - Store the desired register order in the array `reg_alloc_order'.
- - Element 0 should be the register to allocate first; element 1, the
- - next register; and so on.
- -
- - The macro body should not assume anything about the contents of
- - `reg_alloc_order' before execution of the macro.
- -
- - On most machines, it is not necessary to define this macro. */
- -
- - #define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
- -
- /* Macro to conditionally modify fixed_regs/call_used_regs. */
- #define CONDITIONAL_REGISTER_USAGE \
- { \
- --- 350,355 ----
- ***************
- *** 408,413 ****
- --- 391,399 ----
- /* The casts to int placate a compiler on a microvax,
- for cross-compiler testing. */
-
- + /* intel1 - added case of (REGNO)==16 (gbug12)*/
- + /* : (REGNO) == 16 ? 1 \ */
- +
- #define HARD_REGNO_MODE_OK(REGNO, MODE) \
- ((REGNO) < 2 ? 1 \
- : (REGNO) < 4 ? 1 \
- ***************
- *** 479,505 ****
- /* Place in which caller passes the structure value address.
- 0 means push the value on the stack like an argument. */
- #define STRUCT_VALUE 0
- -
- - /* A C expression which can inhibit the returning of certain function
- - values in registers, based on the type of value. A nonzero value
- - says to return the function value in memory, just as large
- - structures are always returned. Here TYPE will be a C expression
- - of type `tree', representing the data type of the value.
- -
- - Note that values of mode `BLKmode' must be explicitly handled by
- - this macro. Also, the option `-fpcc-struct-return' takes effect
- - regardless of this macro. On most systems, it is possible to
- - leave the macro undefined; this causes a default definition to be
- - used, whose value is the constant 1 for `BLKmode' values, and 0
- - otherwise.
- -
- - Do not use this macro to indicate that structures and unions
- - should always be returned in memory. You should instead use
- - `DEFAULT_PCC_STRUCT_RETURN' to indicate this. */
- -
- - #define RETURN_IN_MEMORY(TYPE) \
- - ((TYPE_MODE (TYPE) == BLKmode) || int_size_in_bytes (TYPE) > 12)
- -
-
- /* Define the classes of registers for register constraints in the
- machine description. Also define ranges of constants.
- --- 465,470 ----
- ***************
- *** 529,535 ****
- {
- NO_REGS,
- AREG, DREG, CREG, BREG,
- - AD_REGS, /* %eax/%edx for DImode */
- Q_REGS, /* %eax %ebx %ecx %edx */
- SIREG, DIREG,
- INDEX_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp */
- --- 494,499 ----
- ***************
- *** 548,554 ****
- #define REG_CLASS_NAMES \
- { "NO_REGS", \
- "AREG", "DREG", "CREG", "BREG", \
- - "AD_REGS", \
- "Q_REGS", \
- "SIREG", "DIREG", \
- "INDEX_REGS", \
- --- 512,517 ----
- ***************
- *** 564,573 ****
- #define REG_CLASS_CONTENTS \
- { 0, \
- 0x1, 0x2, 0x4, 0x8, /* AREG, DREG, CREG, BREG */ \
- - 0x3, /* AD_REGS */ \
- 0xf, /* Q_REGS */ \
- 0x10, 0x20, /* SIREG, DIREG */ \
- ! 0x07f, /* INDEX_REGS */ \
- 0x100ff, /* GENERAL_REGS */ \
- 0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \
- 0xff00, /* FLOAT_REGS */ \
- --- 527,535 ----
- #define REG_CLASS_CONTENTS \
- { 0, \
- 0x1, 0x2, 0x4, 0x8, /* AREG, DREG, CREG, BREG */ \
- 0xf, /* Q_REGS */ \
- 0x10, 0x20, /* SIREG, DIREG */ \
- ! 0x1007f, /* INDEX_REGS */ \
- 0x100ff, /* GENERAL_REGS */ \
- 0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \
- 0xff00, /* FLOAT_REGS */ \
- ***************
- *** 578,583 ****
- --- 540,546 ----
- reg number REGNO. This could be a conditional expression
- or could index an array. */
-
- + extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
- #define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
-
- /* When defined, the compiler allows registers explicitly used in the
- ***************
- *** 635,643 ****
- (C) == 'b' ? BREG : \
- (C) == 'c' ? CREG : \
- (C) == 'd' ? DREG : \
- - (C) == 'A' ? AD_REGS : \
- (C) == 'D' ? DIREG : \
- ! (C) == 'S' ? SIREG : NO_REGS)
-
- /* The letters I, J, K, L and M in a register constraint string
- can be used to stand for particular ranges of immediate operands.
- --- 598,605 ----
- (C) == 'b' ? BREG : \
- (C) == 'c' ? CREG : \
- (C) == 'd' ? DREG : \
- (C) == 'D' ? DIREG : \
- ! (C) == 'S' ? SIREG : NO_REGS) /* intel1 changed to e from S */
-
- /* The letters I, J, K, L and M in a register constraint string
- can be used to stand for particular ranges of immediate operands.
- ***************
- *** 649,654 ****
- --- 611,617 ----
- J is for DImode shifts.
- K and L are for an `andsi' optimization.
- M is for shifts that can be executed by the "lea" opcode.
- + O is for block moves intel1
- */
-
- #define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ***************
- *** 657,662 ****
- --- 620,626 ----
- (C) == 'K' ? (VALUE) == 0xff : \
- (C) == 'L' ? (VALUE) == 0xffff : \
- (C) == 'M' ? (VALUE) >= 0 && (VALUE) <= 3 : \
- + (C) == 'O' ? (VALUE) >= 0 && (VALUE) <= 32 : \
- (C) == 'N' ? (VALUE) >= 0 && (VALUE) <= 255 :\
- 0)
-
- ***************
- *** 710,742 ****
- #define CLASS_MAX_NREGS(CLASS, MODE) \
- (FLOAT_CLASS_P (CLASS) ? 1 : \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
- ! /* A C expression whose value is nonzero if pseudos that have been
- ! assigned to registers of class CLASS would likely be spilled
- ! because registers of CLASS are needed for spill registers.
- !
- ! The default value of this macro returns 1 if CLASS has exactly one
- ! register and zero otherwise. On most machines, this default
- ! should be used. Only define this macro to some other expression
- ! if pseudo allocated by `local-alloc.c' end up in memory because
- ! their hard registers were needed for spill registers. If this
- ! macro returns nonzero for those classes, those pseudos will only
- ! be allocated by `global.c', which knows how to reallocate the
- ! pseudo to another register. If there would not be another
- ! register available for reallocation, you should not change the
- ! definition of this macro since the only effect of such a
- ! definition would be to slow down register allocation. */
- !
- ! #define CLASS_LIKELY_SPILLED_P(CLASS) \
- ! (((CLASS) == AREG) \
- ! || ((CLASS) == DREG) \
- ! || ((CLASS) == CREG) \
- ! || ((CLASS) == BREG) \
- ! || ((CLASS) == AD_REGS) \
- ! || ((CLASS) == SIREG) \
- ! || ((CLASS) == DIREG))
-
- -
- /* Stack layout; function entry, exit and calling. */
-
- /* Define this if pushing a word on the stack
- --- 674,764 ----
- #define CLASS_MAX_NREGS(CLASS, MODE) \
- (FLOAT_CLASS_P (CLASS) ? 1 : \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
- +
-
- ! /* A C statement (sans semicolon) to update the integer variable COST
- ! based on the relationship between INSN that is dependent on
- ! DEP_INSN through the dependence LINK. The default is to make no
- ! adjustment to COST. */
- ! #define ADJUST_COST(insn,link,dep_insn,cost) \
- ! { \
- ! rtx next_inst; \
- ! if (GET_CODE (dep_insn) == CALL_INSN) \
- ! (cost) = 0; \
- ! if (GET_CODE (dep_insn) == INSN \
- ! && GET_CODE (PATTERN (dep_insn)) == SET \
- ! && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG \
- ! && GET_CODE (insn) == INSN \
- ! && GET_CODE (PATTERN (insn)) == SET \
- ! && !reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)), \
- ! SET_SRC (PATTERN (insn)))) \
- ! { \
- ! (cost) = 0; \
- ! } \
- ! if (GET_CODE (insn) == JUMP_INSN) \
- ! { \
- ! (cost) = 0; \
- ! } \
- ! if (TARGET_PENTIUM) \
- ! { \
- ! if (cost !=0 && is_fp_insn (insn) && is_fp_insn (dep_insn) \
- ! && !is_fp_dest (dep_insn)) \
- ! { \
- ! (cost) = 0; \
- ! } \
- ! if (agi_dependent (insn, dep_insn)) \
- ! { \
- ! (cost) = 3; \
- ! } \
- ! else if (GET_CODE (insn) == INSN \
- ! && GET_CODE (PATTERN (insn)) == SET \
- ! && SET_DEST (PATTERN (insn)) == cc0_rtx \
- ! && (next_inst = next_nonnote_insn (insn)) \
- ! && GET_CODE (next_inst) == JUMP_INSN) \
- ! { /* compare probably paired with jump */ \
- ! (cost) = 0; \
- ! } \
- ! } \
- ! else \
- ! if(!is_fp_dest (dep_insn)) \
- ! { \
- ! if(!agi_dependent (insn, dep_insn)) \
- ! (cost) = 0; \
- ! else if (TARGET_486) \
- ! (cost) = 2; \
- ! } \
- ! else \
- ! if(is_fp_store (insn) && is_fp_insn (dep_insn) \
- ! && NEXT_INSN (insn) && NEXT_INSN (NEXT_INSN (insn)) \
- ! && NEXT_INSN (NEXT_INSN (NEXT_INSN (insn))) \
- ! && (GET_CODE (NEXT_INSN (insn)) == INSN) \
- ! && (GET_CODE (NEXT_INSN (NEXT_INSN (insn))) == JUMP_INSN) \
- ! && (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) \
- ! == NOTE) \
- ! && NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) \
- ! == NOTE_INSN_LOOP_END) \
- ! { \
- ! (cost) = 3; \
- ! } \
- ! }
- !
- !
- ! #define ADJUST_BLOCKAGE(last_insn,insn,blockage) \
- ! { \
- ! if(is_fp_store (last_insn) && is_fp_insn (insn) \
- ! && NEXT_INSN (last_insn) && NEXT_INSN (NEXT_INSN (last_insn)) \
- ! && NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn))) \
- ! && (GET_CODE (NEXT_INSN (last_insn)) == INSN) \
- ! && (GET_CODE (NEXT_INSN (NEXT_INSN (last_insn))) == JUMP_INSN) \
- ! && (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn)))) \
- ! == NOTE) \
- ! && NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn)))) \
- ! == NOTE_INSN_LOOP_END) \
- ! { \
- ! (blockage) = 3; \
- ! } \
- ! }
-
- /* Stack layout; function entry, exit and calling. */
-
- /* Define this if pushing a word on the stack
- ***************
- *** 887,988 ****
- } \
- }
-
- - /* A C statement or compound statement to output to FILE some
- - assembler code to initialize basic-block profiling for the current
- - object module. This code should call the subroutine
- - `__bb_init_func' once per object module, passing it as its sole
- - argument the address of a block allocated in the object module.
- -
- - The name of the block is a local symbol made with this statement:
- -
- - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
- -
- - Of course, since you are writing the definition of
- - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
- - can take a short cut in the definition of this macro and use the
- - name that you know will result.
- -
- - The first word of this block is a flag which will be nonzero if the
- - object module has already been initialized. So test this word
- - first, and do not call `__bb_init_func' if the flag is nonzero. */
- -
- - #undef FUNCTION_BLOCK_PROFILER
- - #define FUNCTION_BLOCK_PROFILER(STREAM, LABELNO) \
- - do \
- - { \
- - static int num_func = 0; \
- - rtx xops[8]; \
- - char block_table[80], false_label[80]; \
- - \
- - ASM_GENERATE_INTERNAL_LABEL (block_table, "LPBX", 0); \
- - ASM_GENERATE_INTERNAL_LABEL (false_label, "LPBZ", num_func); \
- - \
- - xops[0] = const0_rtx; \
- - xops[1] = gen_rtx (SYMBOL_REF, VOIDmode, block_table); \
- - xops[2] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, false_label)); \
- - xops[3] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, "__bb_init_func")); \
- - xops[4] = gen_rtx (MEM, Pmode, xops[1]); \
- - xops[5] = stack_pointer_rtx; \
- - xops[6] = GEN_INT (4); \
- - xops[7] = gen_rtx (REG, Pmode, 0); /* eax */ \
- - \
- - CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE; \
- - CONSTANT_POOL_ADDRESS_P (xops[2]) = TRUE; \
- - \
- - output_asm_insn (AS2(cmp%L4,%0,%4), xops); \
- - output_asm_insn (AS1(jne,%2), xops); \
- - \
- - if (!flag_pic) \
- - output_asm_insn (AS1(push%L1,%1), xops); \
- - else \
- - { \
- - output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \
- - output_asm_insn (AS1 (push%L7,%7), xops); \
- - } \
- - \
- - output_asm_insn (AS1(call,%P3), xops); \
- - output_asm_insn (AS2(add%L0,%6,%5), xops); \
- - ASM_OUTPUT_INTERNAL_LABEL (STREAM, "LPBZ", num_func); \
- - num_func++; \
- - } \
- - while (0)
- -
- -
- - /* A C statement or compound statement to increment the count
- - associated with the basic block number BLOCKNO. Basic blocks are
- - numbered separately from zero within each compilation. The count
- - associated with block number BLOCKNO is at index BLOCKNO in a
- - vector of words; the name of this array is a local symbol made
- - with this statement:
- -
- - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2);
- -
- - Of course, since you are writing the definition of
- - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
- - can take a short cut in the definition of this macro and use the
- - name that you know will result. */
- -
- - #define BLOCK_PROFILER(STREAM, BLOCKNO) \
- - do \
- - { \
- - rtx xops[1], cnt_rtx; \
- - char counts[80]; \
- - \
- - ASM_GENERATE_INTERNAL_LABEL (counts, "LPBX", 2); \
- - cnt_rtx = gen_rtx (SYMBOL_REF, VOIDmode, counts); \
- - SYMBOL_REF_FLAG (cnt_rtx) = TRUE; \
- - \
- - if (BLOCKNO) \
- - cnt_rtx = plus_constant (cnt_rtx, (BLOCKNO)*4); \
- - \
- - if (flag_pic) \
- - cnt_rtx = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, cnt_rtx); \
- - \
- - xops[0] = gen_rtx (MEM, SImode, cnt_rtx); \
- - output_asm_insn (AS1(inc%L0,%0), xops); \
- - } \
- - while (0)
- -
- /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
- the stack pointer does not matter. The value is tested only in
- functions that have frame pointers.
- --- 909,914 ----
- ***************
- *** 1146,1180 ****
- After reload, it makes no difference, since pseudo regs have
- been eliminated by then. */
-
-
- ! /* Non strict versions, pseudos are ok */
- ! #define REG_OK_FOR_INDEX_NONSTRICT_P(X) \
- ! (REGNO (X) < STACK_POINTER_REGNUM \
- ! || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
- ! #define REG_OK_FOR_BASE_NONSTRICT_P(X) \
- ! (REGNO (X) <= STACK_POINTER_REGNUM \
- ! || REGNO (X) == ARG_POINTER_REGNUM \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
- ! #define REG_OK_FOR_STRREG_NONSTRICT_P(X) \
- (REGNO (X) == 4 || REGNO (X) == 5 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
- ! /* Strict versions, hard registers only */
- ! #define REG_OK_FOR_INDEX_STRICT_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
- ! #define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
- ! #define REG_OK_FOR_STRREG_STRICT_P(X) \
- ! (REGNO_OK_FOR_DIREG_P (REGNO (X)) || REGNO_OK_FOR_SIREG_P (REGNO (X)))
-
- ! #ifndef REG_OK_STRICT
- ! #define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X)
- ! #define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X)
- ! #define REG_OK_FOR_STRREG_P(X) REG_OK_FOR_STRREG_NONSTRICT_P(X)
-
- - #else
- - #define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P(X)
- - #define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P(X)
- - #define REG_OK_FOR_STRREG_P(X) REG_OK_FOR_STRREG_STRICT_P(X)
- #endif
-
- /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- --- 1072,1107 ----
- After reload, it makes no difference, since pseudo regs have
- been eliminated by then. */
-
- + #ifndef REG_OK_STRICT
-
- ! /* Nonzero if X is a hard reg that can be used as an index or if
- ! it is a pseudo reg. */
-
- ! #define REG_OK_FOR_INDEX_P(X) \
- ! (REGNO (X) < STACK_POINTER_REGNUM \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
- ! /* Nonzero if X is a hard reg that can be used as a base reg
- ! of if it is a pseudo reg. */
- ! /* ?wfs */
- !
- ! #define REG_OK_FOR_BASE_P(X) \
- ! (REGNO (X) <= STACK_POINTER_REGNUM \
- ! || REGNO (X) == ARG_POINTER_REGNUM \
- ! || REGNO(X) >= FIRST_PSEUDO_REGISTER)
- !
- ! #define REG_OK_FOR_STRREG_P(X) \
- (REGNO (X) == 4 || REGNO (X) == 5 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
- ! #else
-
- ! /* Nonzero if X is a hard reg that can be used as an index. */
- ! #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
- ! /* Nonzero if X is a hard reg that can be used as a base reg. */
- ! #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
- ! #define REG_OK_FOR_STRREG_P(X) \
- ! (REGNO_OK_FOR_DIREG_P (REGNO (X)) || REGNO_OK_FOR_SIREG_P (REGNO (X)))
-
- #endif
-
- /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- ***************
- *** 1200,1221 ****
-
- #define LEGITIMATE_CONSTANT_P(X) 1
-
- ! #ifdef REG_OK_STRICT
- ! #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- ! { \
- ! if (legitimate_address_p (MODE, X, 1)) \
- ! goto ADDR; \
- ! }
-
- ! #else
- ! #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- { \
- ! if (legitimate_address_p (MODE, X, 0)) \
- goto ADDR; \
- }
-
- - #endif
- -
- /* Try machine-dependent ways of modifying an illegitimate address
- to be legitimate. If we find one, return the new, valid address.
- This macro is used in only one place: `memory_address' in explow.c.
- --- 1127,1188 ----
-
- #define LEGITIMATE_CONSTANT_P(X) 1
-
- ! #define GO_IF_INDEXABLE_BASE(X, ADDR) \
- ! if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR
-
- ! #define LEGITIMATE_INDEX_REG_P(X) \
- ! (GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))
- !
- ! /* Return 1 if X is an index or an index times a scale. */
- !
- ! #define LEGITIMATE_INDEX_P(X) \
- ! (LEGITIMATE_INDEX_REG_P (X) \
- ! || (GET_CODE (X) == MULT \
- ! && LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \
- ! && GET_CODE (XEXP (X, 1)) == CONST_INT \
- ! && (INTVAL (XEXP (X, 1)) == 2 \
- ! || INTVAL (XEXP (X, 1)) == 4 \
- ! || INTVAL (XEXP (X, 1)) == 8)))
- !
- ! /* Go to ADDR if X is an index term, a base reg, or a sum of those. */
- !
- ! #define GO_IF_INDEXING(X, ADDR) \
- ! { if (LEGITIMATE_INDEX_P (X)) goto ADDR; \
- ! GO_IF_INDEXABLE_BASE (X, ADDR); \
- ! if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0))) \
- ! { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \
- ! if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \
- ! { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } }
- !
- ! /* We used to allow this, but it isn't ever used.
- ! || ((GET_CODE (X) == POST_DEC || GET_CODE (X) == POST_INC) \
- ! && REG_P (XEXP (X, 0)) \
- ! && REG_OK_FOR_STRREG_P (XEXP (X, 0))) \
- ! */
- !
- ! #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- { \
- ! if (CONSTANT_ADDRESS_P (X) \
- ! && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (X))) \
- goto ADDR; \
- + GO_IF_INDEXING (X, ADDR); \
- + if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
- + { \
- + rtx x0 = XEXP (X, 0); \
- + if (! flag_pic || ! SYMBOLIC_CONST (XEXP (X, 1))) \
- + { GO_IF_INDEXING (x0, ADDR); } \
- + else if (x0 == pic_offset_table_rtx) \
- + goto ADDR; \
- + else if (GET_CODE (x0) == PLUS) \
- + { \
- + if (XEXP (x0, 0) == pic_offset_table_rtx) \
- + { GO_IF_INDEXABLE_BASE (XEXP (x0, 1), ADDR); } \
- + if (XEXP (x0, 1) == pic_offset_table_rtx) \
- + { GO_IF_INDEXABLE_BASE (XEXP (x0, 0), ADDR); } \
- + } \
- + } \
- }
-
- /* Try machine-dependent ways of modifying an illegitimate address
- to be legitimate. If we find one, return the new, valid address.
- This macro is used in only one place: `memory_address' in explow.c.
- ***************
- *** 1237,1249 ****
- When -fpic is used, special handling is needed for symbolic references.
- See comments by legitimize_pic_address in i386.c for details. */
-
- ! #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
- ! { \
- ! rtx orig_x = (X); \
- ! (X) = legitimize_address (X, OLDX, MODE); \
- ! if (memory_address_p (MODE, X)) \
- ! goto WIN; \
- ! }
-
- /* Nonzero if the constant value X is a legitimate general operand
- when generating PIC code. It is given that flag_pic is on and
- --- 1204,1244 ----
- When -fpic is used, special handling is needed for symbolic references.
- See comments by legitimize_pic_address in i386.c for details. */
-
- ! #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
- ! { extern rtx legitimize_pic_address (); \
- ! int ch = (X) != (OLDX); \
- ! if (flag_pic && SYMBOLIC_CONST (X)) \
- ! { \
- ! (X) = legitimize_pic_address (X, 0); \
- ! if (memory_address_p (MODE, X)) \
- ! goto WIN; \
- ! } \
- ! if (GET_CODE (X) == PLUS) \
- ! { if (GET_CODE (XEXP (X, 0)) == MULT) \
- ! ch = 1, XEXP (X, 0) = force_operand (XEXP (X, 0), 0); \
- ! if (GET_CODE (XEXP (X, 1)) == MULT) \
- ! ch = 1, XEXP (X, 1) = force_operand (XEXP (X, 1), 0); \
- ! if (ch && GET_CODE (XEXP (X, 1)) == REG \
- ! && GET_CODE (XEXP (X, 0)) == REG) \
- ! goto WIN; \
- ! if (flag_pic && SYMBOLIC_CONST (XEXP (X, 1))) \
- ! ch = 1, (X) = legitimize_pic_address (X, 0); \
- ! if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \
- ! if (GET_CODE (XEXP (X, 0)) == REG) \
- ! { register rtx temp = gen_reg_rtx (Pmode); \
- ! register rtx val = force_operand (XEXP (X, 1), temp); \
- ! if (val != temp) emit_move_insn (temp, val); \
- ! XEXP (X, 1) = temp; \
- ! goto WIN; } \
- ! else if (GET_CODE (XEXP (X, 1)) == REG) \
- ! { register rtx temp = gen_reg_rtx (Pmode); \
- ! register rtx val = force_operand (XEXP (X, 0), temp); \
- ! if (val != temp) emit_move_insn (temp, val); \
- ! XEXP (X, 0) = temp; \
- ! goto WIN; }}}
- !
- ! /* intel1 */
- ! #define REWRITE_ADDRESS(x) rewrite_address(x)
-
- /* Nonzero if the constant value X is a legitimate general operand
- when generating PIC code. It is given that flag_pic is on and
- ***************
- *** 1381,1386 ****
- --- 1376,1385 ----
- /* Nonzero if access to memory by bytes is slow and undesirable. */
- #define SLOW_BYTE_ACCESS 0
-
- + /* intel1 */
- + /* Nonzero if access to memory by shorts is slow and undesirable. */
- + #define SLOW_SHORT_ACCESS 1
- +
- /* Define if shifts truncate the shift count
- which implies one can omit a sign-extension or zero-extension
- of a shift count. */
- ***************
- *** 1512,1517 ****
- --- 1511,1517 ----
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-
- + extern struct rtx_def *i386_compare_op0, *i386_compare_op1;
- extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
-
- /* Tell final.c how to eliminate redundant test instructions. */
- ***************
- *** 1519,1524 ****
- --- 1519,1528 ----
- /* Here we define machine-dependent flags and fields in cc_status
- (see `conditions.h'). */
-
- + /* intel1 Set if the cc value is was actually from the 80387 and
- + we are testing eax directly (i.e. no sahf) */
- + #define CC_TEST_AX 020000
- +
- /* Set if the cc value is actually in the 80387, so a floating point
- conditional branch must be output. */
- #define CC_IN_80387 04000
- ***************
- *** 1816,1827 ****
- { fputs ("argp", FILE); break; } \
- if (STACK_TOP_P (X)) \
- { fputs ("st(0)", FILE); break; } \
- - if (FP_REG_P (X)) \
- - { fputs (hi_name[REGNO(X)], FILE); break; } \
- switch (GET_MODE_SIZE (GET_MODE (X))) \
- { \
- ! default: \
- ! fputs ("e", FILE); \
- case 2: \
- fputs (hi_name[REGNO (X)], FILE); \
- break; \
- --- 1820,1831 ----
- { fputs ("argp", FILE); break; } \
- if (STACK_TOP_P (X)) \
- { fputs ("st(0)", FILE); break; } \
- switch (GET_MODE_SIZE (GET_MODE (X))) \
- { \
- ! case 12: \
- ! case 8: \
- ! case 4: \
- ! if (! FP_REG_P (X)) fputs ("e", FILE); \
- case 2: \
- fputs (hi_name[REGNO (X)], FILE); \
- break; \
- ***************
- *** 1857,1865 ****
- #define RET return ""
- #define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx))
-
- - /* Functions in i386.c */
- - extern void override_options ();
- - extern void order_regs_for_local_alloc ();
- extern int i386_valid_decl_attribute_p ();
- extern int i386_valid_type_attribute_p ();
- extern int i386_return_pops_args ();
- --- 1861,1866 ----
- ***************
- *** 1868,1909 ****
- extern void function_arg_advance ();
- extern struct rtx_def *function_arg ();
- extern int function_arg_partial_nregs ();
- - extern void output_op_from_reg ();
- - extern void output_to_reg ();
- - extern char *singlemove_string ();
- - extern char *output_move_double ();
- - extern char *output_move_memory ();
- - extern char *output_move_pushmem ();
- - extern int standard_80387_constant_p ();
- - extern char *output_move_const_single ();
- - extern int symbolic_operand ();
- - extern int call_insn_operand ();
- - extern int expander_call_insn_operand ();
- - extern int symbolic_reference_mentioned_p ();
- - extern void emit_pic_move ();
- - extern void function_prologue ();
- - extern int simple_386_epilogue ();
- - extern void function_epilogue ();
- - extern int legitimate_address_p ();
- - extern struct rtx_def *legitimize_pic_address ();
- - extern struct rtx_def *legitimize_address ();
- - extern void print_operand ();
- - extern void print_operand_address ();
- - extern void notice_update_cc ();
- - extern void split_di ();
- - extern int binary_387_op ();
- - extern int shift_op ();
- - extern int VOIDmode_compare_op ();
- - extern char *output_387_binary_op ();
- - extern char *output_fix_trunc ();
- - extern char *output_float_compare ();
- - extern char *output_fp_cc0_set ();
- - extern void save_386_machine_status ();
- - extern void restore_386_machine_status ();
- - extern void clear_386_stack_locals ();
- - extern struct rtx_def *assign_386_stack_local ();
-
- ! /* Variables in i386.c */
- extern char *i386_reg_alloc_order; /* register allocation order */
- extern char *i386_regparm_string; /* # registers to use to pass args */
- extern char *i386_align_loops_string; /* power of two alignment for loops */
- --- 1869,1876 ----
- extern void function_arg_advance ();
- extern struct rtx_def *function_arg ();
- extern int function_arg_partial_nregs ();
-
- ! /* Variables in i386.c */
- extern char *i386_reg_alloc_order; /* register allocation order */
- extern char *i386_regparm_string; /* # registers to use to pass args */
- extern char *i386_align_loops_string; /* power of two alignment for loops */
- ***************
- *** 1913,1932 ****
- extern int i386_align_loops; /* power of two alignment for loops */
- extern int i386_align_jumps; /* power of two alignment for non-loop jumps */
- extern int i386_align_funcs; /* power of two alignment for functions */
- ! extern char *hi_reg_name[]; /* names for 16 bit regs */
- ! extern char *qi_reg_name[]; /* names for 8 bit regs (low) */
- ! extern char *qi_high_reg_name[]; /* names for 8 bit regs (high) */
- ! extern enum reg_class regclass_map[]; /* smalled class containing REGNO */
- ! extern struct rtx_def *i386_compare_op0; /* operand 0 for comparisons */
- ! extern struct rtx_def *i386_compare_op1; /* operand 1 for comparisons */
- !
- ! /* External variables used */
- ! extern int optimize; /* optimization level */
- ! extern int obey_regdecls; /* TRUE if stupid register allocation */
- !
- ! /* External functions used */
- ! extern struct rtx_def *force_operand ();
- !
- /*
- Local variables:
- version-control: t
- --- 1880,1888 ----
- extern int i386_align_loops; /* power of two alignment for loops */
- extern int i386_align_jumps; /* power of two alignment for non-loop jumps */
- extern int i386_align_funcs; /* power of two alignment for functions */
- ! /*extern char *hi_reg_name[]; /* names for 16 bit regs */
- ! /*extern char *qi_reg_name[]; /* names for 8 bit regs (low) */
- ! /*extern char *qi_high_reg_name[]; /* names for 8 bit regs (high) */
- /*
- Local variables:
- version-control: t
- diff -rNci gcc-2.7.2/config/i386/i386.md gcc-2.7.2p/config/i386/i386.md
- *** gcc-2.7.2/config/i386/i386.md Mon Aug 21 17:27:58 1995
- --- gcc-2.7.2p/config/i386/i386.md Tue Jan 23 09:35:00 1996
- ***************
- *** 2,7 ****
- --- 2,10 ----
- ;; Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc.
- ;; Mostly by William Schelter.
-
- + ;; Pentium cpu support and other enhancements by Tevi Devor Intel Corp.
- + ;; (tevi@iil.intel.com).
- +
- ;; This file is part of GNU CC.
-
- ;; GNU CC is free software; you can redistribute it and/or modify
- ***************
- *** 72,77 ****
- --- 75,110 ----
- ;; actually generating RTL. The bCOND or sCOND (emitted immediately
- ;; after the tstM or cmp) will actually emit the tstM or cmpM.
-
- + ;intel1
- + (define_attr "type" "fld,integer,fpop,fpdiv"
- + (const_string "integer"))
- +
- + ;; Functional units intel1
- + (define_function_unit "fp" 1 0
- + (and (eq_attr "type" "fpop")
- + (ne (symbol_ref "x86_cpu") (symbol_ref "PROCESSOR_PENTIUM")))
- + 5 5)
- +
- + (define_function_unit "fp" 1 0
- + (and (eq_attr "type" "fpop")
- + (eq (symbol_ref "x86_cpu") (symbol_ref "PROCESSOR_PENTIUM")))
- + 3 0)
- +
- + (define_function_unit "fp" 1 0
- + (eq_attr "type" "fpdiv")
- + 10 10)
- +
- + (define_function_unit "fp" 1 0
- + (eq_attr "type" "fld")
- + 1 0)
- +
- + (define_function_unit "integer" 1 0
- + (and (eq_attr "type" "integer")
- + (ne (symbol_ref "x86_cpu") (symbol_ref "PROCESSOR_386")))
- + 2 0)
- +
- +
- +
- (define_insn "tstsi_1"
- [(set (cc0)
- (match_operand:SI 0 "nonimmediate_operand" "rm"))]
- ***************
- *** 144,247 ****
- DONE;
- }")
-
- ! (define_insn "tstsf_cc"
- ! [(set (cc0)
- ! (match_operand:SF 0 "register_operand" "f"))
- ! (clobber (match_scratch:HI 1 "=a"))]
- ! "TARGET_80387 && ! TARGET_IEEE_FP"
- ! "*
- ! {
- ! if (! STACK_TOP_P (operands[0]))
- ! abort ();
- !
- ! output_asm_insn (\"ftst\", operands);
- !
- ! if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! output_asm_insn (AS1 (fstp,%y0), operands);
- !
- ! return output_fp_cc0_set (insn);
- ! }")
- !
- ! ;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode
- ! ;; isn't IEEE compliant.
- !
- ! (define_expand "tstsf"
- ! [(parallel [(set (cc0)
- ! (match_operand:SF 0 "register_operand" ""))
- ! (clobber (match_scratch:HI 1 ""))])]
- ! "TARGET_80387 && ! TARGET_IEEE_FP"
- ! "
- ! {
- ! i386_compare_gen = gen_tstsf_cc;
- ! i386_compare_op0 = operands[0];
- ! DONE;
- ! }")
- !
- ! (define_insn "tstdf_cc"
- ! [(set (cc0)
- ! (match_operand:DF 0 "register_operand" "f"))
- ! (clobber (match_scratch:HI 1 "=a"))]
- ! "TARGET_80387 && ! TARGET_IEEE_FP"
- ! "*
- ! {
- ! if (! STACK_TOP_P (operands[0]))
- ! abort ();
- !
- ! output_asm_insn (\"ftst\", operands);
- !
- ! if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! output_asm_insn (AS1 (fstp,%y0), operands);
- !
- ! return output_fp_cc0_set (insn);
- ! }")
- !
- ! ;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
- ! ;; isn't IEEE compliant.
- !
- ! (define_expand "tstdf"
- ! [(parallel [(set (cc0)
- ! (match_operand:DF 0 "register_operand" ""))
- ! (clobber (match_scratch:HI 1 ""))])]
- ! "TARGET_80387 && ! TARGET_IEEE_FP"
- ! "
- ! {
- ! i386_compare_gen = gen_tstdf_cc;
- ! i386_compare_op0 = operands[0];
- ! DONE;
- ! }")
- !
- ! (define_insn "tstxf_cc"
- ! [(set (cc0)
- ! (match_operand:XF 0 "register_operand" "f"))
- ! (clobber (match_scratch:HI 1 "=a"))]
- ! "TARGET_80387 && ! TARGET_IEEE_FP"
- ! "*
- ! {
- ! if (! STACK_TOP_P (operands[0]))
- ! abort ();
- !
- ! output_asm_insn (\"ftst\", operands);
- !
- ! if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! output_asm_insn (AS1 (fstp,%y0), operands);
- !
- ! return output_fp_cc0_set (insn);
- ! }")
- !
- ! ;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
- ! ;; isn't IEEE compliant.
- !
- ! (define_expand "tstxf"
- ! [(parallel [(set (cc0)
- ! (match_operand:XF 0 "register_operand" ""))
- ! (clobber (match_scratch:HI 1 ""))])]
- ! "TARGET_80387 && ! TARGET_IEEE_FP"
- ! "
- ! {
- ! i386_compare_gen = gen_tstxf_cc;
- ! i386_compare_op0 = operands[0];
- ! DONE;
- ! }")
-
- ;;- compare instructions. See comments above tstM patterns about
- ;; expansion of these insns.
- --- 177,281 ----
- DONE;
- }")
-
- ! ;; intel1
- ! ;;(define_insn "tstsf_cc"
- ! ;; [(set (cc0)
- ! ;; (match_operand:SF 0 "register_operand" "f"))
- ! ;; (clobber (match_scratch:HI 1 "=a"))]
- ! ;; "TARGET_80387 && ! TARGET_IEEE_FP"
- ! ;; "*
- ! ;;{
- ! ;; if (! STACK_TOP_P (operands[0]))
- ! ;; abort ();
- ! ;;
- ! ;; output_asm_insn (\"ftst\", operands);
- ! ;;
- ! ;; if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! ;; output_asm_insn (AS1 (fstp,%y0), operands);
- ! ;;
- ! ;; return (char *) output_fp_cc0_set (insn);
- ! ;;}")
- ! ;;
- ! ;;;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode
- ! ;;;; isn't IEEE compliant.
- ! ;;
- ! ;;(define_expand "tstsf"
- ! ;; [(parallel [(set (cc0)
- ! ;; (match_operand:SF 0 "register_operand" ""))
- ! ;; (clobber (match_scratch:HI 1 ""))])]
- ! ;; "TARGET_80387 && ! TARGET_IEEE_FP"
- ! ;; "
- ! ;;{
- ! ;; i386_compare_gen = gen_tstsf_cc;
- ! ;; i386_compare_op0 = operands[0];
- ! ;; DONE;
- ! ;;}")
- ! ;;
- ! ;;(define_insn "tstdf_cc"
- ! ;; [(set (cc0)
- ! ;; (match_operand:DF 0 "register_operand" "f"))
- ! ;; (clobber (match_scratch:HI 1 "=a"))]
- ! ;; "TARGET_80387 && ! TARGET_IEEE_FP"
- ! ;; "*
- ! ;;{
- ! ;; if (! STACK_TOP_P (operands[0]))
- ! ;; abort ();
- ! ;;
- ! ;; output_asm_insn (\"ftst\", operands);
- ! ;;
- ! ;; if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! ;; output_asm_insn (AS1 (fstp,%y0), operands);
- ! ;;
- ! ;; return (char *) output_fp_cc0_set (insn);
- ! ;;}")
- ! ;;
- ! ;;;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
- ! ;;;; isn't IEEE compliant.
- ! ;;
- ! ;;(define_expand "tstdf"
- ! ;; [(parallel [(set (cc0)
- ! ;; (match_operand:DF 0 "register_operand" ""))
- ! ;; (clobber (match_scratch:HI 1 ""))])]
- ! ;; "TARGET_80387 && ! TARGET_IEEE_FP"
- ! ;; "
- ! ;;{
- ! ;; i386_compare_gen = gen_tstdf_cc;
- ! ;; i386_compare_op0 = operands[0];
- ! ;; DONE;
- ! ;;}")
- !
- ! ;;(define_insn "tstxf_cc"
- ! ;; [(set (cc0)
- ! ;; (match_operand:XF 0 "register_operand" "f"))
- ! ;; (clobber (match_scratch:HI 1 "=a"))]
- ! ;; "TARGET_80387 && ! TARGET_IEEE_FP"
- ! ;; "*
- ! ;;{
- ! ;; if (! STACK_TOP_P (operands[0]))
- ! ;; abort ();
- ! ;;
- ! ;; output_asm_insn (\"ftst\", operands);
- ! ;;
- ! ;; if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! ;; output_asm_insn (AS1 (fstp,%y0), operands);
- ! ;;
- ! ;; return (char *) output_fp_cc0_set (insn);
- ! ;;}")
- ! ;;
- ! ;;;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
- ! ;;;; isn't IEEE compliant.
- ! ;;
- ! ;;(define_expand "tstxf"
- ! ;; [(parallel [(set (cc0)
- ! ;; (match_operand:XF 0 "register_operand" ""))
- ! ;; (clobber (match_scratch:HI 1 ""))])]
- ! ;; "TARGET_80387 && ! TARGET_IEEE_FP"
- ! ;; "
- ! ;;{
- ! ;; i386_compare_gen = gen_tstxf_cc;
- ! ;; i386_compare_op0 = operands[0];
- ! ;; DONE;
- ! ;;}")
-
- ;;- compare instructions. See comments above tstM patterns about
- ;; expansion of these insns.
- ***************
- *** 343,397 ****
- ;; SFmode, there is the normal insn, and an insn where the second operand
- ;; is converted to the desired mode.
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- ! [(match_operand:XF 0 "nonimmediate_operand" "f")
- ! (match_operand:XF 1 "nonimmediate_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:XF 0 "register_operand" "f")
- (float:XF
- ! (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(float:XF
- ! (match_operand:SI 0 "nonimmediate_operand" "rm"))
- (match_operand:XF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:XF 0 "register_operand" "f")
- (float_extend:XF
- ! (match_operand:DF 1 "nonimmediate_operand" "fm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:XF 0 "register_operand" "f")
- (float_extend:XF
- ! (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 377,432 ----
- ;; SFmode, there is the normal insn, and an insn where the second operand
- ;; is converted to the desired mode.
-
- + ;;intel1 operand 1 and 2 changed from nonimmediate_operand to general_operand
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- ! [(match_operand:XF 0 "general_operand" "f")
- ! (match_operand:XF 1 "general_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:XF 0 "register_operand" "f")
- (float:XF
- ! (match_operand:SI 1 "general_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(float:XF
- ! (match_operand:SI 0 "general_operand" "rm"))
- (match_operand:XF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:XF 0 "register_operand" "f")
- (float_extend:XF
- ! (match_operand:DF 1 "general_operand" "fm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:XF 0 "register_operand" "f")
- (float_extend:XF
- ! (match_operand:SF 1 "general_operand" "fm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 399,415 ****
- (match_operand:XF 1 "register_operand" "f")))
- (clobber (match_scratch:HI 2 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- ! [(match_operand:DF 0 "nonimmediate_operand" "f,fm")
- ! (match_operand:DF 1 "nonimmediate_operand" "fm,f")]))
- (clobber (match_scratch:HI 3 "=a,a"))]
- "TARGET_80387
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 434,450 ----
- (match_operand:XF 1 "register_operand" "f")))
- (clobber (match_scratch:HI 2 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- ! [(match_operand:DF 0 "general_operand" "f,fm")
- ! (match_operand:DF 1 "general_operand" "fm,f")]))
- (clobber (match_scratch:HI 3 "=a,a"))]
- "TARGET_80387
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 419,425 ****
- (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 454,460 ----
- (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 429,435 ****
- (match_operand:DF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 464,470 ----
- (match_operand:DF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 439,445 ****
- (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 474,480 ----
- (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 449,455 ****
- (match_operand:DF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 484,501 ----
- (match_operand:DF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
- !
- ! ;;intel1
- ! (define_insn ""
- ! [(set (cc0)
- ! (match_operator 2 "VOIDmode_compare_op"
- ! [(float_extend:DF
- ! (match_operand:SF 0 "register_operand" "f"))
- ! (match_operand:DF 1 "general_operand" "fm")]))
- ! (clobber (match_scratch:HI 3 "=a"))]
- ! "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 457,463 ****
- (match_operand:DF 1 "register_operand" "f")))
- (clobber (match_scratch:HI 2 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- ;; These two insns will never be generated by combine due to the mode of
- ;; the COMPARE.
- --- 503,509 ----
- (match_operand:DF 1 "register_operand" "f")))
- (clobber (match_scratch:HI 2 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- ;; These two insns will never be generated by combine due to the mode of
- ;; the COMPARE.
- ***************
- *** 468,474 ****
- ; (match_operand:SF 1 "register_operand" "f"))))
- ; (clobber (match_scratch:HI 2 "=a"))]
- ; "TARGET_80387"
- ! ; "* return output_float_compare (insn, operands);")
- ;
- ;(define_insn ""
- ; [(set (cc0)
- --- 514,520 ----
- ; (match_operand:SF 1 "register_operand" "f"))))
- ; (clobber (match_scratch:HI 2 "=a"))]
- ; "TARGET_80387"
- ! ; "* return (char *) output_float_compare (insn, operands);")
- ;
- ;(define_insn ""
- ; [(set (cc0)
- ***************
- *** 477,493 ****
- ; (match_operand:DF 1 "register_operand" "f")))
- ; (clobber (match_scratch:HI 2 "=a"))]
- ; "TARGET_80387"
- ! ; "* return output_float_compare (insn, operands);")
-
- (define_insn "cmpsf_cc_1"
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:SF 0 "nonimmediate_operand" "f,fm")
- ! (match_operand:SF 1 "nonimmediate_operand" "fm,f")]))
- (clobber (match_scratch:HI 3 "=a,a"))]
- "TARGET_80387
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 523,540 ----
- ; (match_operand:DF 1 "register_operand" "f")))
- ; (clobber (match_scratch:HI 2 "=a"))]
- ; "TARGET_80387"
- ! ; "* return (char *) output_float_compare (insn, operands);")
-
- + ;;intel1 operand 1 changed from nonimmediate_operand to general_operand
- (define_insn "cmpsf_cc_1"
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:SF 0 "nonimmediate_operand" "f,fm")
- ! (match_operand:SF 1 "general_operand" "fm,f")]))
- (clobber (match_scratch:HI 3 "=a,a"))]
- "TARGET_80387
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 497,503 ****
- (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 544,550 ----
- (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 507,513 ****
- (match_operand:SF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- --- 554,560 ----
- (match_operand:SF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_insn ""
- [(set (cc0)
- ***************
- *** 515,526 ****
- (match_operand:SF 1 "register_operand" "f")))
- (clobber (match_scratch:HI 2 "=a"))]
- "TARGET_80387"
- ! "* return output_float_compare (insn, operands);")
-
- (define_expand "cmpxf"
- [(set (cc0)
- ! (compare (match_operand:XF 0 "register_operand" "")
- ! (match_operand:XF 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "
- {
- --- 562,573 ----
- (match_operand:SF 1 "register_operand" "f")))
- (clobber (match_scratch:HI 2 "=a"))]
- "TARGET_80387"
- ! "* return (char *) output_float_compare (insn, operands);")
-
- (define_expand "cmpxf"
- [(set (cc0)
- ! (compare (match_operand:XF 0 "register_operand" "")
- ! (match_operand:XF 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "
- {
- ***************
- *** 531,540 ****
- DONE;
- }")
-
- (define_expand "cmpdf"
- [(set (cc0)
- (compare (match_operand:DF 0 "register_operand" "")
- ! (match_operand:DF 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "
- {
- --- 578,588 ----
- DONE;
- }")
-
- + ;;intel1 operand 1 changed from nonimmediate_operand to general_operand
- (define_expand "cmpdf"
- [(set (cc0)
- (compare (match_operand:DF 0 "register_operand" "")
- ! (match_operand:DF 1 "general_operand" "")))]
- "TARGET_80387"
- "
- {
- ***************
- *** 545,554 ****
- DONE;
- }")
-
- (define_expand "cmpsf"
- [(set (cc0)
- (compare (match_operand:SF 0 "register_operand" "")
- ! (match_operand:SF 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "
- {
- --- 593,603 ----
- DONE;
- }")
-
- + ;;intel1 operand 1 changed from nonimmediate_operand to general_operand
- (define_expand "cmpsf"
- [(set (cc0)
- (compare (match_operand:SF 0 "register_operand" "")
- ! (match_operand:SF 1 "general_operand" "")))]
- "TARGET_80387"
- "
- {
- ***************
- *** 561,577 ****
-
- (define_expand "cmpxf_cc"
- [(parallel [(set (cc0)
- ! (compare (match_operand:XF 0 "register_operand" "")
- ! (match_operand:XF 1 "register_operand" "")))
- ! (clobber (match_scratch:HI 2 ""))])]
- "TARGET_80387"
- "")
-
- (define_expand "cmpxf_ccfpeq"
- [(parallel [(set (cc0)
- ! (compare:CCFPEQ (match_operand:XF 0 "register_operand" "")
- ! (match_operand:XF 1 "register_operand" "")))
- ! (clobber (match_scratch:HI 2 ""))])]
- "TARGET_80387"
- "
- {
- --- 610,626 ----
-
- (define_expand "cmpxf_cc"
- [(parallel [(set (cc0)
- ! (compare (match_operand:XF 0 "register_operand" "")
- ! (match_operand:XF 1 "register_operand" "")))
- ! (clobber (match_scratch:HI 2 ""))])]
- "TARGET_80387"
- "")
-
- (define_expand "cmpxf_ccfpeq"
- [(parallel [(set (cc0)
- ! (compare:CCFPEQ (match_operand:XF 0 "register_operand" "")
- ! (match_operand:XF 1 "register_operand" "")))
- ! (clobber (match_scratch:HI 2 ""))])]
- "TARGET_80387"
- "
- {
- ***************
- *** 742,748 ****
- (define_insn ""
- [(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_operand" "g"))]
- ! "TARGET_386"
- "push%L0 %1")
-
- ;; On a 486, it is faster to move MEM to a REG and then push, rather than
- --- 791,797 ----
- (define_insn ""
- [(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_operand" "g"))]
- ! "! TARGET_486"
- "push%L0 %1")
-
- ;; On a 486, it is faster to move MEM to a REG and then push, rather than
- ***************
- *** 750,763 ****
-
- (define_insn ""
- [(set (match_operand:SI 0 "push_operand" "=<")
- - (match_operand:SI 1 "nonmemory_operand" "ri"))]
- - "!TARGET_386 && TARGET_MOVE"
- - "push%L0 %1")
- -
- - (define_insn ""
- - [(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_operand" "ri"))]
- ! "!TARGET_386 && !TARGET_MOVE"
- "push%L0 %1")
-
- ;; General case of fullword move.
- --- 799,806 ----
-
- (define_insn ""
- [(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_operand" "ri"))]
- ! "TARGET_486"
- "push%L0 %1")
-
- ;; General case of fullword move.
- ***************
- *** 775,789 ****
-
- if (flag_pic && SYMBOLIC_CONST (operands[1]))
- emit_pic_move (operands, SImode);
- -
- - /* Don't generate memory->memory moves, go through a register */
- - else if (TARGET_MOVE
- - && (reload_in_progress | reload_completed) == 0
- - && GET_CODE (operands[0]) == MEM
- - && GET_CODE (operands[1]) == MEM)
- - {
- - operands[1] = force_reg (SImode, operands[1]);
- - }
- }")
-
- ;; On i486, incl reg is faster than movl $1,reg.
- --- 818,823 ----
- ***************
- *** 791,797 ****
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g,r")
- (match_operand:SI 1 "general_operand" "ri,m"))]
- ! "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
- "*
- {
- rtx link;
- --- 825,831 ----
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g,r")
- (match_operand:SI 1 "general_operand" "ri,m"))]
- ! ""
- "*
- {
- rtx link;
- ***************
- *** 810,861 ****
- /* Fastest way to change a 0 to a 1. */
- return AS1 (inc%L0,%0);
-
- - if (flag_pic && SYMBOLIC_CONST (operands[1]))
- - return AS2 (lea%L0,%a1,%0);
- -
- return AS2 (mov%L0,%1,%0);
- }")
-
- (define_insn ""
- [(set (match_operand:HI 0 "push_operand" "=<")
- (match_operand:HI 1 "general_operand" "g"))]
- ! "TARGET_386"
- ! "push%W0 %1")
- !
- ! (define_insn ""
- ! [(set (match_operand:HI 0 "push_operand" "=<")
- ! (match_operand:HI 1 "nonmemory_operand" "ri"))]
- ! "!TARGET_386 && TARGET_MOVE"
- ! "push%W0 %1")
- !
- ! (define_insn ""
- ! [(set (match_operand:HI 0 "push_operand" "=<")
- ! (match_operand:HI 1 "general_operand" "ri"))]
- ! "!TARGET_386 && !TARGET_MOVE"
- "push%W0 %1")
-
- ;; On i486, an incl and movl are both faster than incw and movw.
-
- ! (define_expand "movhi"
- ! [(set (match_operand:HI 0 "general_operand" "")
- ! (match_operand:HI 1 "general_operand" ""))]
- ! ""
- ! "
- ! {
- ! /* Don't generate memory->memory moves, go through a register */
- ! if (TARGET_MOVE
- ! && (reload_in_progress | reload_completed) == 0
- ! && GET_CODE (operands[0]) == MEM
- ! && GET_CODE (operands[1]) == MEM)
- ! {
- ! operands[1] = force_reg (HImode, operands[1]);
- ! }
- ! }")
- !
- ! (define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=g,r")
- (match_operand:HI 1 "general_operand" "ri,m"))]
- ! "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
- "*
- {
- rtx link;
- --- 844,864 ----
- /* Fastest way to change a 0 to a 1. */
- return AS1 (inc%L0,%0);
-
- return AS2 (mov%L0,%1,%0);
- }")
-
- (define_insn ""
- [(set (match_operand:HI 0 "push_operand" "=<")
- (match_operand:HI 1 "general_operand" "g"))]
- ! ""
- "push%W0 %1")
-
- ;; On i486, an incl and movl are both faster than incw and movw.
-
- ! (define_insn "movhi"
- [(set (match_operand:HI 0 "general_operand" "=g,r")
- (match_operand:HI 1 "general_operand" "ri,m"))]
- ! ""
- "*
- {
- rtx link;
- ***************
- *** 885,910 ****
- return AS2 (mov%W0,%1,%0);
- }")
-
- ! (define_expand "movstricthi"
- ! [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
- ! (match_operand:HI 1 "general_operand" ""))]
- ! ""
- ! "
- ! {
- ! /* Don't generate memory->memory moves, go through a register */
- ! if (TARGET_MOVE
- ! && (reload_in_progress | reload_completed) == 0
- ! && GET_CODE (operands[0]) == MEM
- ! && GET_CODE (operands[1]) == MEM)
- ! {
- ! operands[1] = force_reg (HImode, operands[1]);
- ! }
- ! }")
- !
- ! (define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r"))
- (match_operand:HI 1 "general_operand" "ri,m"))]
- ! "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
- "*
- {
- rtx link;
- --- 888,897 ----
- return AS2 (mov%W0,%1,%0);
- }")
-
- ! (define_insn "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r"))
- (match_operand:HI 1 "general_operand" "ri,m"))]
- ! ""
- "*
- {
- rtx link;
- ***************
- *** 932,955 ****
- ;; the amount pushed up to a halfword.
- (define_insn ""
- [(set (match_operand:QI 0 "push_operand" "=<")
- ! (match_operand:QI 1 "immediate_operand" "n"))]
- ""
- - "* return AS1 (push%W0,%1);")
- -
- - (define_insn ""
- - [(set (match_operand:QI 0 "push_operand" "=<")
- - (match_operand:QI 1 "nonimmediate_operand" "q"))]
- - "!TARGET_MOVE"
- - "*
- - {
- - operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
- - return AS1 (push%W0,%1);
- - }")
- -
- - (define_insn ""
- - [(set (match_operand:QI 0 "push_operand" "=<")
- - (match_operand:QI 1 "register_operand" "q"))]
- - "TARGET_MOVE"
- "*
- {
- operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
- --- 919,926 ----
- ;; the amount pushed up to a halfword.
- (define_insn ""
- [(set (match_operand:QI 0 "push_operand" "=<")
- ! (match_operand:QI 1 "general_operand" "q"))]
- ""
- "*
- {
- operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
- ***************
- *** 961,986 ****
- ;; ??? Do a recognizer for zero_extract that looks just like this, but reads
- ;; or writes %ah, %bh, %ch, %dh.
-
- ! (define_expand "movqi"
- ! [(set (match_operand:QI 0 "general_operand" "")
- ! (match_operand:QI 1 "general_operand" ""))]
- ! ""
- ! "
- ! {
- ! /* Don't generate memory->memory moves, go through a register */
- ! if (TARGET_MOVE
- ! && (reload_in_progress | reload_completed) == 0
- ! && GET_CODE (operands[0]) == MEM
- ! && GET_CODE (operands[1]) == MEM)
- ! {
- ! operands[1] = force_reg (QImode, operands[1]);
- ! }
- ! }")
- !
- ! (define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=q,*r,qm")
- (match_operand:QI 1 "general_operand" "*g,q,qn"))]
- ! "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
- "*
- {
- rtx link;
- --- 932,941 ----
- ;; ??? Do a recognizer for zero_extract that looks just like this, but reads
- ;; or writes %ah, %bh, %ch, %dh.
-
- ! (define_insn "movqi"
- [(set (match_operand:QI 0 "general_operand" "=q,*r,qm")
- (match_operand:QI 1 "general_operand" "*g,q,qn"))]
- ! ""
- "*
- {
- rtx link;
- ***************
- *** 1015,1040 ****
- ;; If operands[1] is a constant, then an andl/orl sequence would be
- ;; faster.
-
- ! (define_expand "movstrictqi"
- ! [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
- ! (match_operand:QI 1 "general_operand" ""))]
- ! ""
- ! "
- ! {
- ! /* Don't generate memory->memory moves, go through a register */
- ! if (TARGET_MOVE
- ! && (reload_in_progress | reload_completed) == 0
- ! && GET_CODE (operands[0]) == MEM
- ! && GET_CODE (operands[1]) == MEM)
- ! {
- ! operands[1] = force_reg (QImode, operands[1]);
- ! }
- ! }")
- !
- ! (define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q"))
- (match_operand:QI 1 "general_operand" "*qn,m"))]
- ! "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
- "*
- {
- rtx link;
- --- 970,979 ----
- ;; If operands[1] is a constant, then an andl/orl sequence would be
- ;; faster.
-
- ! (define_insn "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q"))
- (match_operand:QI 1 "general_operand" "*qn,m"))]
- ! ""
- "*
- {
- rtx link;
- ***************
- *** 1063,1105 ****
- return AS2 (mov%B0,%1,%0);
- }")
-
- ! (define_expand "movsf"
- ! [(set (match_operand:SF 0 "general_operand" "")
- ! (match_operand:SF 1 "general_operand" ""))]
- ! ""
- ! "
- ! {
- ! /* Special case memory->memory moves and pushes */
- ! if (TARGET_MOVE
- ! && (reload_in_progress | reload_completed) == 0
- ! && GET_CODE (operands[0]) == MEM
- ! && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode)))
- ! {
- ! rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode))
- ! ? gen_movsf_push
- ! : gen_movsf_mem;
- !
- ! emit_insn ((*genfunc) (operands[0], operands[1]));
- ! DONE;
- ! }
- !
- ! /* If we are loading a floating point constant that isn't 0 or 1 into a register,
- ! indicate we need the pic register loaded. This could be optimized into stores
- ! of constants if the target eventually moves to memory, but better safe than
- ! sorry. */
- ! if (flag_pic
- ! && GET_CODE (operands[0]) != MEM
- ! && GET_CODE (operands[1]) == CONST_DOUBLE
- ! && !standard_80387_constant_p (operands[1]))
- ! {
- ! current_function_uses_pic_offset_table = 1;
- ! }
- ! }")
- !
- ! (define_insn "movsf_push_nomove"
- [(set (match_operand:SF 0 "push_operand" "=<,<")
- (match_operand:SF 1 "general_operand" "gF,f"))]
- ! "!TARGET_MOVE"
- "*
- {
- if (STACK_REG_P (operands[1]))
- --- 1002,1011 ----
- return AS2 (mov%B0,%1,%0);
- }")
-
- ! (define_insn ""
- [(set (match_operand:SF 0 "push_operand" "=<,<")
- (match_operand:SF 1 "general_operand" "gF,f"))]
- ! ""
- "*
- {
- if (STACK_REG_P (operands[1]))
- ***************
- *** 1124,1184 ****
- return AS1 (push%L1,%1);
- }")
-
- ! (define_insn "movsf_push"
- ! [(set (match_operand:SF 0 "push_operand" "=<,<,<,<")
- ! (match_operand:SF 1 "general_operand" "rF,f,m,m"))
- ! (clobber (match_scratch:SI 2 "=X,X,r,X"))]
- ! ""
- ! "*
- ! {
- ! if (STACK_REG_P (operands[1]))
- ! {
- ! rtx xops[3];
- !
- ! if (! STACK_TOP_P (operands[1]))
- ! abort ();
- !
- ! xops[0] = AT_SP (SFmode);
- ! xops[1] = GEN_INT (4);
- ! xops[2] = stack_pointer_rtx;
- !
- ! output_asm_insn (AS2 (sub%L2,%1,%2), xops);
- !
- ! if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! output_asm_insn (AS1 (fstp%S0,%0), xops);
- ! else
- ! output_asm_insn (AS1 (fst%S0,%0), xops);
- ! RET;
- ! }
- !
- ! else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG)
- ! return AS1 (push%L1,%1);
- !
- ! else
- ! {
- ! output_asm_insn (AS2 (mov%L2,%1,%2), operands);
- ! return AS1 (push%L2,%2);
- ! }
- ! }")
-
- ! ;; Special memory<->memory pattern that combine will recreate from the
- ! ;; moves to pseudos.
- ! (define_insn "movsf_mem"
- ! [(set (match_operand:SF 0 "memory_operand" "=m")
- ! (match_operand:SF 1 "memory_operand" "m"))
- ! (clobber (match_scratch:SI 2 "=&r"))]
- ""
- "*
- {
- ! output_asm_insn (AS2 (mov%L2,%1,%2), operands);
- ! return AS2 (mov%L0,%2,%0);
- }")
-
- ! ;; For the purposes of regclass, prefer FLOAT_REGS.
- ! (define_insn "movsf_normal"
- [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm")
- (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))]
- ! "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
- "*
- {
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- --- 1030,1053 ----
- return AS1 (push%L1,%1);
- }")
-
- ! ;; Allow MEM-MEM moves before reload. The reload class for such a
- ! ;; move will be ALL_REGS. PREFERRED_RELOAD_CLASS will narrow this to
- ! ;; GENERAL_REGS. For the purposes of regclass, prefer FLOAT_REGS.
-
- ! ;;intel1
- ! (define_insn "memmovsf"
- ! [(set (match_operand:SF 0 "memory_operand" "=r,m")
- ! (match_operand:SF 1 "memory_operand" "m,r"))]
- ""
- "*
- {
- ! return (char *) singlemove_string (operands);
- }")
-
- ! (define_insn "movsf"
- [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm")
- (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))]
- ! ""
- "*
- {
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- ***************
- *** 1220,1286 ****
- /* Handle other kinds of reads to the 387 */
-
- if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
- ! return output_move_const_single (operands);
-
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
-
- /* Handle all SFmode moves not involving the 387 */
-
- ! return singlemove_string (operands);
- ! }")
- !
- ! (define_insn "swapsf"
- ! [(set (match_operand:SF 0 "register_operand" "f")
- ! (match_operand:SF 1 "register_operand" "f"))
- ! (set (match_dup 1)
- ! (match_dup 0))]
- ! ""
- ! "*
- ! {
- ! if (STACK_TOP_P (operands[0]))
- ! return AS1 (fxch,%1);
- ! else
- ! return AS1 (fxch,%0);
- ! }")
- !
- ! (define_expand "movdf"
- ! [(set (match_operand:DF 0 "general_operand" "")
- ! (match_operand:DF 1 "general_operand" ""))]
- ! ""
- ! "
- ! {
- ! /* Special case memory->memory moves and pushes */
- ! if (TARGET_MOVE
- ! && (reload_in_progress | reload_completed) == 0
- ! && GET_CODE (operands[0]) == MEM
- ! && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode)))
- ! {
- ! rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode))
- ! ? gen_movdf_push
- ! : gen_movdf_mem;
- !
- ! emit_insn ((*genfunc) (operands[0], operands[1]));
- ! DONE;
- ! }
- !
- ! /* If we are loading a floating point constant that isn't 0 or 1 into a register,
- ! indicate we need the pic register loaded. This could be optimized into stores
- ! of constants if the target eventually moves to memory, but better safe than
- ! sorry. */
- ! if (flag_pic
- ! && GET_CODE (operands[0]) != MEM
- ! && GET_CODE (operands[1]) == CONST_DOUBLE
- ! && !standard_80387_constant_p (operands[1]))
- ! {
- ! current_function_uses_pic_offset_table = 1;
- ! }
- ! }")
-
- ! (define_insn "movdf_push_nomove"
- [(set (match_operand:DF 0 "push_operand" "=<,<")
- (match_operand:DF 1 "general_operand" "gF,f"))]
- ! "!TARGET_MOVE"
- "*
- {
- if (STACK_REG_P (operands[1]))
- --- 1089,1109 ----
- /* Handle other kinds of reads to the 387 */
-
- if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
- ! return (char *) output_move_const_single (operands);
-
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
-
- /* Handle all SFmode moves not involving the 387 */
-
- ! return (char *) singlemove_string (operands);
- ! }"[(set_attr "type" "fld")])
-
- ! ;;should change to handle the memory operands[1] without doing df push..
- ! (define_insn ""
- [(set (match_operand:DF 0 "push_operand" "=<,<")
- (match_operand:DF 1 "general_operand" "gF,f"))]
- ! ""
- "*
- {
- if (STACK_REG_P (operands[1]))
- ***************
- *** 1301,1355 ****
- RET;
- }
- else
- ! return output_move_double (operands);
- }")
-
- ! (define_insn "movdf_push"
- ! [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<")
- ! (match_operand:DF 1 "general_operand" "rF,f,o,o,o"))
- ! (clobber (match_scratch:SI 2 "=X,X,&r,&r,X"))
- ! (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))]
- ""
- "*
- {
- ! if (STACK_REG_P (operands[1]))
- ! {
- ! rtx xops[3];
- !
- ! xops[0] = AT_SP (SFmode);
- ! xops[1] = GEN_INT (8);
- ! xops[2] = stack_pointer_rtx;
- !
- ! output_asm_insn (AS2 (sub%L2,%1,%2), xops);
- !
- ! if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! output_asm_insn (AS1 (fstp%Q0,%0), xops);
- ! else
- ! output_asm_insn (AS1 (fst%Q0,%0), xops);
- !
- ! RET;
- ! }
- !
- ! else if (GET_CODE (operands[1]) != MEM)
- ! return output_move_double (operands);
- !
- else
- ! return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);
- }")
-
- ! (define_insn "movdf_mem"
- ! [(set (match_operand:DF 0 "memory_operand" "=o,o")
- ! (match_operand:DF 1 "memory_operand" "o,o"))
- ! (clobber (match_scratch:SI 2 "=&r,&r"))
- ! (clobber (match_scratch:SI 3 "=&r,X"))]
- ""
- ! "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);")
-
- ! ;; For the purposes of regclass, prefer FLOAT_REGS.
- ! (define_insn "movdf_normal"
- ! [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm")
- ! (match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
- ! "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
- "*
- {
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- --- 1124,1164 ----
- RET;
- }
- else
- ! return (char *) output_move_double (operands);
- }")
-
- ! (define_insn "swapdf"
- ! [(set (match_operand:DF 0 "register_operand" "f")
- ! (match_operand:DF 1 "register_operand" "f"))
- ! (set (match_dup 1)
- ! (match_dup 0))]
- ""
- "*
- {
- ! if (STACK_TOP_P (operands[0]))
- ! return AS1 (fxch,%1);
- else
- ! return AS1 (fxch,%0);
- }")
-
- ! ;; Allow MEM-MEM moves before reload. The reload class for such a
- ! ;; move will be ALL_REGS. PREFERRED_RELOAD_CLASS will narrow this to
- ! ;; GENERAL_REGS. For the purposes of regclass, prefer FLOAT_REGS.
- !
- ! ;;intel1
- ! (define_insn "memmovdf"
- ! [(set (match_operand:DF 0 "memory_operand" "=r,m")
- ! (match_operand:DF 1 "memory_operand" "m,r"))]
- ""
- ! "*
- ! {
- ! return (char *) output_move_double (operands);
- ! }")
-
- ! (define_insn "movdf"
- ! [(set (match_operand:DF 0 "general_operand" "=*rfm,*rf,f,!*rm")
- ! (match_operand:DF 1 "general_operand" "*rf,*rfm,fG,fF"))]
- ! ""
- "*
- {
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- ***************
- *** 1391,1458 ****
- /* Handle other kinds of reads to the 387 */
-
- if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
- ! return output_move_const_single (operands);
-
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
-
- /* Handle all DFmode moves not involving the 387 */
-
- ! return output_move_double (operands);
- ! }")
-
- ! (define_insn "swapdf"
- ! [(set (match_operand:DF 0 "register_operand" "f")
- ! (match_operand:DF 1 "register_operand" "f"))
- ! (set (match_dup 1)
- ! (match_dup 0))]
- ! ""
- ! "*
- ! {
- ! if (STACK_TOP_P (operands[0]))
- ! return AS1 (fxch,%1);
- ! else
- ! return AS1 (fxch,%0);
- ! }")
- !
- ! (define_expand "movxf"
- ! [(set (match_operand:XF 0 "general_operand" "")
- ! (match_operand:XF 1 "general_operand" ""))]
- ! ""
- ! "
- ! {
- ! /* Special case memory->memory moves and pushes */
- ! if (TARGET_MOVE
- ! && (reload_in_progress | reload_completed) == 0
- ! && GET_CODE (operands[0]) == MEM
- ! && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode)))
- ! {
- ! rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode))
- ! ? gen_movxf_push
- ! : gen_movxf_mem;
- !
- ! emit_insn ((*genfunc) (operands[0], operands[1]));
- ! DONE;
- ! }
- !
- ! /* If we are loading a floating point constant that isn't 0 or 1 into a register,
- ! indicate we need the pic register loaded. This could be optimized into stores
- ! of constants if the target eventually moves to memory, but better safe than
- ! sorry. */
- ! if (flag_pic
- ! && GET_CODE (operands[0]) != MEM
- ! && GET_CODE (operands[1]) == CONST_DOUBLE
- ! && !standard_80387_constant_p (operands[1]))
- ! {
- ! current_function_uses_pic_offset_table = 1;
- ! }
- ! }")
- !
- !
- ! (define_insn "movxf_push_nomove"
- [(set (match_operand:XF 0 "push_operand" "=<,<")
- (match_operand:XF 1 "general_operand" "gF,f"))]
- ! "!TARGET_MOVE"
- "*
- {
- if (STACK_REG_P (operands[1]))
- --- 1200,1219 ----
- /* Handle other kinds of reads to the 387 */
-
- if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
- ! return (char *) output_move_const_single (operands);
-
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
-
- /* Handle all DFmode moves not involving the 387 */
-
- ! return (char *) output_move_double (operands);
- ! }"[(set_attr "type" "fld")])
-
- ! (define_insn ""
- [(set (match_operand:XF 0 "push_operand" "=<,<")
- (match_operand:XF 1 "general_operand" "gF,f"))]
- ! ""
- "*
- {
- if (STACK_REG_P (operands[1]))
- ***************
- *** 1471,1523 ****
- RET;
- }
- else
- ! return output_move_double (operands);
- }")
-
- ! (define_insn "movxf_push"
- ! [(set (match_operand:XF 0 "push_operand" "=<,<,<,<,<")
- ! (match_operand:XF 1 "general_operand" "rF,f,o,o,o"))
- ! (clobber (match_scratch:SI 2 "=X,X,&r,&r,X"))
- ! (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))]
- ""
- "*
- {
- ! if (STACK_REG_P (operands[1]))
- ! {
- ! rtx xops[3];
- !
- ! xops[0] = AT_SP (SFmode);
- ! xops[1] = GEN_INT (12);
- ! xops[2] = stack_pointer_rtx;
- !
- ! output_asm_insn (AS2 (sub%L2,%1,%2), xops);
- ! output_asm_insn (AS1 (fstp%T0,%0), xops);
- ! if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- ! output_asm_insn (AS1 (fld%T0,%0), xops);
- !
- ! RET;
- ! }
- !
- ! else if (GET_CODE (operands[1]) != MEM
- ! || GET_CODE (operands[2]) != REG)
- ! return output_move_double (operands);
- !
- else
- ! return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);
- }")
-
- ! (define_insn "movxf_mem"
- ! [(set (match_operand:XF 0 "memory_operand" "=o,o")
- ! (match_operand:XF 1 "memory_operand" "o,o"))
- ! (clobber (match_scratch:SI 2 "=&r,&r"))
- ! (clobber (match_scratch:SI 3 "=&r,X"))]
- ! ""
- ! "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);")
- !
- ! (define_insn "movxf_normal"
- [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm")
- (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
- ! "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
- "*
- {
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- --- 1232,1260 ----
- RET;
- }
- else
- ! return (char *) output_move_double (operands);
- }")
-
- ! (define_insn "swapxf"
- ! [(set (match_operand:XF 0 "register_operand" "f")
- ! (match_operand:XF 1 "register_operand" "f"))
- ! (set (match_dup 1)
- ! (match_dup 0))]
- ""
- "*
- {
- ! if (STACK_TOP_P (operands[0]))
- ! return AS1 (fxch,%1);
- else
- ! return AS1 (fxch,%0);
- }")
-
- ! (define_insn "movxf"
- [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm")
- (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
- ! ;; [(set (match_operand:XF 0 "general_operand" "=*rf,*rfm,f,!*rm")
- ! ;; (match_operand:XF 1 "general_operand" "*rfm,*rf,fG,fF"))]
- ! ""
- "*
- {
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- ***************
- *** 1560,1620 ****
- /* Handle other kinds of reads to the 387 */
-
- if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
- ! return output_move_const_single (operands);
-
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
-
- /* Handle all XFmode moves not involving the 387 */
-
- ! return output_move_double (operands);
- ! }")
- !
- ! (define_insn "swapxf"
- ! [(set (match_operand:XF 0 "register_operand" "f")
- ! (match_operand:XF 1 "register_operand" "f"))
- ! (set (match_dup 1)
- ! (match_dup 0))]
- ! ""
- ! "*
- ! {
- ! if (STACK_TOP_P (operands[0]))
- ! return AS1 (fxch,%1);
- ! else
- ! return AS1 (fxch,%0);
- }")
-
- (define_insn ""
- ! [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
- ! (match_operand:DI 1 "general_operand" "riF,o,o,o"))
- ! (clobber (match_scratch:SI 2 "=X,&r,&r,X"))
- ! (clobber (match_scratch:SI 3 "=X,&r,X,X"))]
- ""
- "*
- {
- ! if (GET_CODE (operands[1]) != MEM)
- ! return output_move_double (operands);
- !
- ! else
- ! return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
- }")
-
- (define_insn "movdi"
- ! [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm")
- ! (match_operand:DI 1 "general_operand" "o,o,m,riF"))
- ! (clobber (match_scratch:SI 2 "=&r,&r,X,X"))
- ! (clobber (match_scratch:SI 3 "=&r,X,X,X"))]
- ""
- "*
- {
- ! rtx low[2], high[2], xop[6];
- !
- ! if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
- ! return output_move_double (operands);
- ! else
- ! return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
- }")
- -
-
- ;;- conversion instructions
- ;;- NONE
- --- 1297,1329 ----
- /* Handle other kinds of reads to the 387 */
-
- if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
- ! return (char *) output_move_const_single (operands);
-
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
-
- /* Handle all XFmode moves not involving the 387 */
-
- ! return (char *) output_move_double (operands);
- }")
-
- (define_insn ""
- ! [(set (match_operand:DI 0 "push_operand" "=<")
- ! (match_operand:DI 1 "general_operand" "roiF"))]
- ""
- "*
- {
- ! return (char *) output_move_double (operands);
- }")
-
- (define_insn "movdi"
- ! [(set (match_operand:DI 0 "general_operand" "=r,rm")
- ! (match_operand:DI 1 "general_operand" "m,riF"))]
- ""
- "*
- {
- ! return (char *) output_move_double (operands);
- }")
-
- ;;- conversion instructions
- ;;- NONE
- ***************
- *** 1629,1635 ****
- ""
- "*
- {
- ! if ((!TARGET_386 || REGNO (operands[0]) == 0)
- && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
- {
- rtx xops[2];
- --- 1338,1344 ----
- ""
- "*
- {
- ! if (((TARGET_486 || TARGET_PENTIUM) || REGNO (operands[0]) == 0)
- && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
- {
- rtx xops[2];
- ***************
- *** 1639,1644 ****
- --- 1348,1372 ----
- RET;
- }
-
- + if ((((TARGET_486 || TARGET_PENTIUM)))
- + && !reg_overlap_mentioned_p(operands[0],operands[1]))
- + {
- + rtx xops[2];
- + output_asm_insn (AS2 (xor%L0,%0,%0),operands);
- + output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
- + RET;
- + }
- +
- + if ((TARGET_486 || TARGET_PENTIUM))
- + {
- + rtx xops[2];
- + xops[0] = operands[0];
- + xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xffff);
- + output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
- + output_asm_insn (AS2 (and%L0,%1,%k0), xops);
- + RET;
- + }
- +
- #ifdef INTEL_SYNTAX
- return AS2 (movzx,%1,%0);
- #else
- ***************
- *** 1653,1659 ****
- ""
- "*
- {
- ! if ((!TARGET_386 || REGNO (operands[0]) == 0)
- && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
- {
- rtx xops[2];
- --- 1381,1387 ----
- ""
- "*
- {
- ! if (((TARGET_486 || TARGET_PENTIUM) || REGNO (operands[0]) == 0)
- && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
- {
- rtx xops[2];
- ***************
- *** 1663,1668 ****
- --- 1391,1416 ----
- RET;
- }
-
- + /* intel1 */
- + if ((((TARGET_486 || TARGET_PENTIUM))) &&
- + reg_fits_class_p (operands[0], Q_REGS, 0, SImode))
- + {
- + rtx xops[2];
- + if(!reg_overlap_mentioned_p(operands[0],operands[1]))
- + {
- + output_asm_insn (AS2 (xor%L0,%k0,%k0),operands);
- + output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
- + }
- + else
- + {
- + xops[0] = operands[0];
- + xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xff);
- + output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
- + output_asm_insn (AS2 (and%L0,%1,%k0), xops);
- + }
- + RET;
- + }
- +
- #ifdef INTEL_SYNTAX
- return AS2 (movzx,%1,%0);
- #else
- ***************
- *** 1677,1683 ****
- ""
- "*
- {
- ! if ((!TARGET_386 || REGNO (operands[0]) == 0)
- && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
- {
- rtx xops[2];
- --- 1425,1431 ----
- ""
- "*
- {
- ! if (((TARGET_486 || TARGET_PENTIUM) || REGNO (operands[0]) == 0)
- && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
- {
- rtx xops[2];
- ***************
- *** 1687,1692 ****
- --- 1435,1471 ----
- RET;
- }
-
- + /* intel1 */
- + if ((((TARGET_486 || TARGET_PENTIUM))) &&
- + reg_fits_class_p (operands[0], Q_REGS, 0, SImode))
- + {
- + rtx xops[2];
- + if(!reg_overlap_mentioned_p(operands[0],operands[1]))
- + {
- + output_asm_insn (AS2 (xor%L0,%0,%0),operands);
- + output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
- + }
- + else
- + {
- + xops[0] = operands[0];
- + xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xff);
- + output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
- + output_asm_insn (AS2 (and%L0,%1,%k0), xops);
- + }
- + RET;
- + }
- +
- + if ((TARGET_486 || TARGET_PENTIUM) && GET_CODE (operands[1]) == REG)
- + {
- + rtx xops[2];
- + xops[0] = operands[0];
- + operands[1] = gen_rtx (REG, SImode, REGNO (operands[1]));
- + xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xff);
- + output_asm_insn (AS2 (mov%L0,%1,%0),operands);
- + output_asm_insn (AS2 (and%L0,%1,%k0), xops);
- + RET;
- + }
- +
- #ifdef INTEL_SYNTAX
- return AS2 (movzx,%1,%0);
- #else
- ***************
- *** 2013,2027 ****
-
- (define_expand "fixuns_truncxfsi2"
- [(set (match_dup 4)
- ! (match_operand:XF 1 "register_operand" ""))
- (parallel [(set (match_dup 2)
- ! (fix:DI (fix:XF (match_dup 4))))
- ! (clobber (match_dup 4))
- ! (clobber (match_dup 5))
- ! (clobber (match_dup 6))
- ! (clobber (match_scratch:SI 7 ""))])
- (set (match_operand:SI 0 "general_operand" "")
- ! (match_dup 3))]
- "TARGET_80387"
- "
- {
- --- 1792,1806 ----
-
- (define_expand "fixuns_truncxfsi2"
- [(set (match_dup 4)
- ! (match_operand:XF 1 "register_operand" ""))
- (parallel [(set (match_dup 2)
- ! (fix:DI (fix:XF (match_dup 4))))
- ! (clobber (match_dup 4))
- ! (clobber (match_dup 5))
- ! (clobber (match_dup 6))
- ! (clobber (match_scratch:SI 7 ""))])
- (set (match_operand:SI 0 "general_operand" "")
- ! (match_dup 3))]
- "TARGET_80387"
- "
- {
- ***************
- *** 2078,2090 ****
-
- (define_expand "fix_truncxfdi2"
- [(set (match_dup 2)
- ! (match_operand:XF 1 "register_operand" ""))
- (parallel [(set (match_operand:DI 0 "general_operand" "")
- ! (fix:DI (fix:XF (match_dup 2))))
- ! (clobber (match_dup 2))
- ! (clobber (match_dup 3))
- ! (clobber (match_dup 4))
- ! (clobber (match_scratch:SI 5 ""))])]
- "TARGET_80387"
- "
- {
- --- 1857,1869 ----
-
- (define_expand "fix_truncxfdi2"
- [(set (match_dup 2)
- ! (match_operand:XF 1 "register_operand" ""))
- (parallel [(set (match_operand:DI 0 "general_operand" "")
- ! (fix:DI (fix:XF (match_dup 2))))
- ! (clobber (match_dup 2))
- ! (clobber (match_dup 3))
- ! (clobber (match_dup 4))
- ! (clobber (match_scratch:SI 5 ""))])]
- "TARGET_80387"
- "
- {
- ***************
- *** 2134,2156 ****
-
- (define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=rm")
- ! (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
- (clobber (match_dup 1))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return output_fix_trunc (insn, operands);")
-
- (define_insn ""
- ! [(set (match_operand:DI 0 "general_operand" "=rm")
- ! (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
- (clobber (match_dup 1))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return output_fix_trunc (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=rm")
- --- 1913,1935 ----
-
- (define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=rm")
- ! (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
- (clobber (match_dup 1))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return (char *) output_fix_trunc (insn, operands);")
-
- (define_insn ""
- ! [(set (match_operand:DI 0 "general_operand" "=rm")
- ! (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
- (clobber (match_dup 1))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return (char *) output_fix_trunc (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=rm")
- ***************
- *** 2160,2176 ****
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return output_fix_trunc (insn, operands);")
-
- ;; Signed MODE_FLOAT conversion to SImode.
-
- (define_expand "fix_truncxfsi2"
- [(parallel [(set (match_operand:SI 0 "general_operand" "")
- ! (fix:SI
- ! (fix:XF (match_operand:XF 1 "register_operand" ""))))
- ! (clobber (match_dup 2))
- ! (clobber (match_dup 3))
- ! (clobber (match_scratch:SI 4 ""))])]
- "TARGET_80387"
- "
- {
- --- 1939,1955 ----
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return (char *) output_fix_trunc (insn, operands);")
-
- ;; Signed MODE_FLOAT conversion to SImode.
-
- (define_expand "fix_truncxfsi2"
- [(parallel [(set (match_operand:SI 0 "general_operand" "")
- ! (fix:SI
- ! (fix:XF (match_operand:XF 1 "register_operand" ""))))
- ! (clobber (match_dup 2))
- ! (clobber (match_dup 3))
- ! (clobber (match_scratch:SI 4 ""))])]
- "TARGET_80387"
- "
- {
- ***************
- *** 2208,2228 ****
-
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
- ! (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return output_fix_trunc (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
- ! (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return output_fix_trunc (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
- --- 1987,2007 ----
-
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
- ! (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return (char *) output_fix_trunc (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
- ! (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return (char *) output_fix_trunc (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
- ***************
- *** 2231,2237 ****
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return output_fix_trunc (insn, operands);")
-
- ;; Conversion between fixed point and floating point.
- ;; The actual pattern that matches these is at the end of this file.
- --- 2010,2016 ----
- (clobber (match_operand:SI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
- "TARGET_80387"
- ! "* return (char *) output_fix_trunc (insn, operands);")
-
- ;; Conversion between fixed point and floating point.
- ;; The actual pattern that matches these is at the end of this file.
- ***************
- *** 2264,2276 ****
-
- (define_expand "floatsixf2"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- (define_expand "floatdixf2"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- --- 2043,2055 ----
-
- (define_expand "floatsixf2"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- (define_expand "floatdixf2"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- ***************
- *** 2278,2284 ****
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (float:XF (match_operand:DI 1 "general_operand" "rm")))]
- "TARGET_80387"
- "*
- {
- --- 2057,2063 ----
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (float:XF (match_operand:DI 1 "general_operand" "rm")))]
- "TARGET_80387"
- "*
- {
- ***************
- *** 2346,2352 ****
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- ! (float:XF (match_operand:SI 1 "general_operand" "m,!*r")))]
- "TARGET_80387"
- "*
- {
- --- 2125,2131 ----
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- ! (float:XF (match_operand:SI 1 "general_operand" "m,!*r")))]
- "TARGET_80387"
- "*
- {
- ***************
- *** 2381,2463 ****
- ;;- add instructions
-
- (define_insn "adddi3"
- ! [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,ro,o,&r,o,o,o")
- ! (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,o,riF,o,or,riF,riF,o")
- ! (match_operand:DI 2 "general_operand" "o,riF,o,0,0,0,oriF,riF,o,o")))
- ! (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r,X,&r,&r,&r"))]
- ""
- "*
- {
- ! rtx low[3], high[3], xops[7], temp;
-
- CC_STATUS_INIT;
-
- - if (rtx_equal_p (operands[0], operands[2]))
- - {
- - temp = operands[1];
- - operands[1] = operands[2];
- - operands[2] = temp;
- - }
- -
- split_di (operands, 3, low, high);
- - if (!rtx_equal_p (operands[0], operands[1]))
- - {
- - xops[0] = high[0];
- - xops[1] = low[0];
- - xops[2] = high[1];
- - xops[3] = low[1];
- -
- - if (GET_CODE (operands[0]) != MEM)
- - {
- - output_asm_insn (AS2 (mov%L1,%3,%1), xops);
- - output_asm_insn (AS2 (mov%L0,%2,%0), xops);
- - }
- - else
- - {
- - xops[4] = high[2];
- - xops[5] = low[2];
- - xops[6] = operands[3];
- - output_asm_insn (AS2 (mov%L6,%3,%6), xops);
- - output_asm_insn (AS2 (add%L6,%5,%6), xops);
- - output_asm_insn (AS2 (mov%L1,%6,%1), xops);
- - output_asm_insn (AS2 (mov%L6,%2,%6), xops);
- - output_asm_insn (AS2 (adc%L6,%4,%6), xops);
- - output_asm_insn (AS2 (mov%L0,%6,%0), xops);
- - RET;
- - }
- - }
- -
- - if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
- - {
- - xops[0] = high[0];
- - xops[1] = low[0];
- - xops[2] = high[2];
- - xops[3] = low[2];
- - xops[4] = operands[3];
- -
- - output_asm_insn (AS2 (mov%L4,%3,%4), xops);
- - output_asm_insn (AS2 (add%L1,%4,%1), xops);
- - output_asm_insn (AS2 (mov%L4,%2,%4), xops);
- - output_asm_insn (AS2 (adc%L0,%4,%0), xops);
- - }
-
- ! else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
- {
- output_asm_insn (AS2 (add%L0,%2,%0), low);
- output_asm_insn (AS2 (adc%L0,%2,%0), high);
- }
- -
- else
- output_asm_insn (AS2 (add%L0,%2,%0), high);
- -
- RET;
- }")
-
- ;; On a 486, it is faster to do movl/addl than to do a single leal if
- ;; operands[1] and operands[2] are both registers.
-
- (define_insn "addsi3"
- ! [(set (match_operand:SI 0 "general_operand" "=?r,rm,r")
- (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0")
- (match_operand:SI 2 "general_operand" "ri,ri,rm")))]
- ""
- --- 2160,2193 ----
- ;;- add instructions
-
- (define_insn "adddi3"
- ! [(set (match_operand:DI 0 "general_operand" "=&r,ro")
- ! (plus:DI (match_operand:DI 1 "general_operand" "%0,0")
- ! (match_operand:DI 2 "general_operand" "o,riF")))]
- ""
- "*
- {
- ! rtx low[3], high[3];
-
- CC_STATUS_INIT;
-
- split_di (operands, 3, low, high);
-
- ! if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
- {
- output_asm_insn (AS2 (add%L0,%2,%0), low);
- output_asm_insn (AS2 (adc%L0,%2,%0), high);
- }
- else
- output_asm_insn (AS2 (add%L0,%2,%0), high);
- RET;
- }")
-
- ;; On a 486, it is faster to do movl/addl than to do a single leal if
- ;; operands[1] and operands[2] are both registers.
-
- + ; intel1 removed ? from first constraint
- (define_insn "addsi3"
- ! [(set (match_operand:SI 0 "general_operand" "=r,rm,r")
- (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0")
- (match_operand:SI 2 "general_operand" "ri,ri,rm")))]
- ""
- ***************
- *** 2468,2487 ****
- if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
- return AS2 (add%L0,%1,%0);
-
- ! if (operands[2] == stack_pointer_rtx)
- ! {
- ! rtx temp;
-
- ! temp = operands[1];
- ! operands[1] = operands[2];
- ! operands[2] = temp;
- ! }
-
- ! if (operands[2] != stack_pointer_rtx)
- ! {
- ! CC_STATUS_INIT;
- ! operands[1] = SET_SRC (PATTERN (insn));
- ! return AS2 (lea%L0,%a1,%0);
- }
-
- output_asm_insn (AS2 (mov%L0,%1,%0), operands);
- --- 2198,2220 ----
- if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
- return AS2 (add%L0,%1,%0);
-
- ! if (! (TARGET_486 || TARGET_PENTIUM) || ! REG_P (operands[2]))
- ! {
- ! CC_STATUS_INIT;
-
- ! if (operands[2] == stack_pointer_rtx)
- ! {
- ! rtx temp;
-
- ! temp = operands[1];
- ! operands[1] = operands[2];
- ! operands[2] = temp;
- ! }
- ! if (operands[2] != stack_pointer_rtx)
- ! {
- ! operands[1] = SET_SRC (PATTERN (insn));
- ! return AS2 (lea%L0,%a1,%0);
- ! }
- }
-
- output_asm_insn (AS2 (mov%L0,%1,%0), operands);
- ***************
- *** 2512,2535 ****
- && GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) & 0xff) == 0)
- {
- - int byteval = (INTVAL (operands[2]) >> 8) & 0xff;
- CC_STATUS_INIT;
-
- ! if (byteval == 1)
- ! return AS1 (inc%B0,%h0);
- ! else if (byteval == 255)
- ! return AS1 (dec%B0,%h0);
-
- - operands[2] = GEN_INT (byteval);
- return AS2 (add%B0,%2,%h0);
- }
-
- if (operands[2] == const1_rtx)
- return AS1 (inc%W0,%0);
-
- ! if (operands[2] == constm1_rtx
- ! || (GET_CODE (operands[2]) == CONST_INT
- ! && INTVAL (operands[2]) == 65535))
- return AS1 (dec%W0,%0);
-
- return AS2 (add%W0,%2,%0);
- --- 2245,2267 ----
- && GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) & 0xff) == 0)
- {
- CC_STATUS_INIT;
-
- ! operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
- !
- ! if (operands[2] == const1_rtx)
- ! return AS1 (inc%B0,%h0);
- !
- ! if (operands[2] == constm1_rtx)
- ! return AS1 (dec%B0,%h0);
-
- return AS2 (add%B0,%2,%h0);
- }
-
- if (operands[2] == const1_rtx)
- return AS1 (inc%W0,%0);
-
- ! if (operands[2] == constm1_rtx)
- return AS1 (dec%W0,%0);
-
- return AS2 (add%W0,%2,%0);
- ***************
- *** 2545,2553 ****
- if (operands[2] == const1_rtx)
- return AS1 (inc%B0,%0);
-
- ! if (operands[2] == constm1_rtx
- ! || (GET_CODE (operands[2]) == CONST_INT
- ! && INTVAL (operands[2]) == 255))
- return AS1 (dec%B0,%0);
-
- return AS2 (add%B0,%2,%0);
- --- 2277,2283 ----
- if (operands[2] == const1_rtx)
- return AS1 (inc%B0,%0);
-
- ! if (operands[2] == constm1_rtx)
- return AS1 (dec%B0,%0);
-
- return AS2 (add%B0,%2,%0);
- ***************
- *** 2580,2586 ****
-
- ;; addsi3 is faster, so put this after.
-
- ! (define_insn "movsi_lea"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:QI 1 "address_operand" "p"))]
- ""
- --- 2310,2316 ----
-
- ;; addsi3 is faster, so put this after.
-
- ! (define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:QI 1 "address_operand" "p"))]
- ""
- ***************
- *** 2610,2617 ****
-
- (define_expand "addxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (plus:XF (match_operand:XF 1 "nonimmediate_operand" "")
- ! (match_operand:XF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- --- 2340,2347 ----
-
- (define_expand "addxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (plus:XF (match_operand:XF 1 "nonimmediate_operand" "")
- ! (match_operand:XF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- ***************
- *** 2632,2697 ****
- ;;- subtract instructions
-
- (define_insn "subdi3"
- ! [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o")
- ! (minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o")
- ! (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o")))
- ! (clobber (match_scratch:SI 3 "=X,X,X,&r,&r"))]
- ""
- "*
- {
- ! rtx low[3], high[3], xops[7];
-
- CC_STATUS_INIT;
-
- split_di (operands, 3, low, high);
-
- ! if (!rtx_equal_p (operands[0], operands[1]))
- ! {
- ! xops[0] = high[0];
- ! xops[1] = low[0];
- ! xops[2] = high[1];
- ! xops[3] = low[1];
- !
- ! if (GET_CODE (operands[0]) != MEM)
- ! {
- ! output_asm_insn (AS2 (mov%L1,%3,%1), xops);
- ! output_asm_insn (AS2 (mov%L0,%2,%0), xops);
- ! }
- ! else
- ! {
- ! xops[4] = high[2];
- ! xops[5] = low[2];
- ! xops[6] = operands[3];
- ! output_asm_insn (AS2 (mov%L6,%3,%6), xops);
- ! output_asm_insn (AS2 (sub%L6,%5,%6), xops);
- ! output_asm_insn (AS2 (mov%L1,%6,%1), xops);
- ! output_asm_insn (AS2 (mov%L6,%2,%6), xops);
- ! output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
- ! output_asm_insn (AS2 (mov%L0,%6,%0), xops);
- ! RET;
- ! }
- ! }
- !
- ! if (GET_CODE (operands[3]) == REG)
- ! {
- ! xops[0] = high[0];
- ! xops[1] = low[0];
- ! xops[2] = high[2];
- ! xops[3] = low[2];
- ! xops[4] = operands[3];
- !
- ! output_asm_insn (AS2 (mov%L4,%3,%4), xops);
- ! output_asm_insn (AS2 (sub%L1,%4,%1), xops);
- ! output_asm_insn (AS2 (mov%L4,%2,%4), xops);
- ! output_asm_insn (AS2 (sbb%L0,%4,%0), xops);
- ! }
- !
- ! else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
- {
- output_asm_insn (AS2 (sub%L0,%2,%0), low);
- output_asm_insn (AS2 (sbb%L0,%2,%0), high);
- }
- -
- else
- output_asm_insn (AS2 (sub%L0,%2,%0), high);
-
- --- 2362,2384 ----
- ;;- subtract instructions
-
- (define_insn "subdi3"
- ! [(set (match_operand:DI 0 "general_operand" "=&r,ro")
- ! (minus:DI (match_operand:DI 1 "general_operand" "0,0")
- ! (match_operand:DI 2 "general_operand" "o,riF")))]
- ""
- "*
- {
- ! rtx low[3], high[3];
-
- CC_STATUS_INIT;
-
- split_di (operands, 3, low, high);
-
- ! if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
- {
- output_asm_insn (AS2 (sub%L0,%2,%0), low);
- output_asm_insn (AS2 (sbb%L0,%2,%0), high);
- }
- else
- output_asm_insn (AS2 (sub%L0,%2,%0), high);
-
- ***************
- *** 2723,2730 ****
-
- (define_expand "subxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (minus:XF (match_operand:XF 1 "nonimmediate_operand" "")
- ! (match_operand:XF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- --- 2410,2417 ----
-
- (define_expand "subxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (minus:XF (match_operand:XF 1 "nonimmediate_operand" "")
- ! (match_operand:XF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- ***************
- *** 2753,2766 ****
-
- (define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=r")
- ! (mult:HI (match_operand:HI 1 "general_operand" "%0")
- (match_operand:HI 2 "general_operand" "r")))]
- "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
- "* return AS2 (imul%W0,%2,%0);")
-
- (define_insn "mulhi3"
- [(set (match_operand:HI 0 "general_operand" "=r,r")
- ! (mult:HI (match_operand:HI 1 "general_operand" "%0,rm")
- (match_operand:HI 2 "general_operand" "g,i")))]
- ""
- "*
- --- 2440,2453 ----
-
- (define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=r")
- ! (mult:SI (match_operand:HI 1 "general_operand" "%0")
- (match_operand:HI 2 "general_operand" "r")))]
- "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
- "* return AS2 (imul%W0,%2,%0);")
-
- (define_insn "mulhi3"
- [(set (match_operand:HI 0 "general_operand" "=r,r")
- ! (mult:SI (match_operand:HI 1 "general_operand" "%0,rm")
- (match_operand:HI 2 "general_operand" "g,i")))]
- ""
- "*
- ***************
- *** 2795,2852 ****
- return AS3 (imul%L0,%2,%1,%0);
- }")
-
- ! (define_insn "umulqihi3"
- [(set (match_operand:HI 0 "general_operand" "=a")
- ! (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
- ! (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
- ""
- "mul%B0 %2")
-
- - (define_insn "mulqihi3"
- - [(set (match_operand:HI 0 "general_operand" "=a")
- - (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
- - (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
- - ""
- - "imul%B0 %2")
- -
- - (define_insn "umulsidi3"
- - [(set (match_operand:DI 0 "register_operand" "=A")
- - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
- - (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
- - "TARGET_WIDE_MULTIPLY"
- - "mul%L0 %2")
- -
- - (define_insn "mulsidi3"
- - [(set (match_operand:DI 0 "register_operand" "=A")
- - (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
- - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
- - "TARGET_WIDE_MULTIPLY"
- - "imul%L0 %2")
- -
- - (define_insn "umulsi3_highpart"
- - [(set (match_operand:SI 0 "register_operand" "=d")
- - (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a"))
- - (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
- - (const_int 32))))
- - (clobber (match_scratch:SI 3 "=a"))]
- - "TARGET_WIDE_MULTIPLY"
- - "mul%L0 %2")
- -
- - (define_insn "smulsi3_highpart"
- - [(set (match_operand:SI 0 "register_operand" "=d")
- - (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a"))
- - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
- - (const_int 32))))
- - (clobber (match_scratch:SI 3 "=a"))]
- - "TARGET_WIDE_MULTIPLY"
- - "imul%L0 %2")
- -
- ;; The patterns that match these are at the end of this file.
-
- (define_expand "mulxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (mult:XF (match_operand:XF 1 "nonimmediate_operand" "")
- ! (match_operand:XF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- --- 2482,2502 ----
- return AS3 (imul%L0,%2,%1,%0);
- }")
-
- ! (define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=a")
- ! (mult:SI (zero_extend:HI
- ! (match_operand:QI 1 "nonimmediate_operand" "%0"))
- ! (zero_extend:HI
- ! (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
- ""
- "mul%B0 %2")
-
- ;; The patterns that match these are at the end of this file.
-
- (define_expand "mulxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (mult:XF (match_operand:XF 1 "nonimmediate_operand" "")
- ! (match_operand:XF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- ***************
- *** 2884,2891 ****
-
- (define_expand "divxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (div:XF (match_operand:XF 1 "nonimmediate_operand" "")
- ! (match_operand:XF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- --- 2534,2541 ----
-
- (define_expand "divxf3"
- [(set (match_operand:XF 0 "register_operand" "")
- ! (div:XF (match_operand:XF 1 "nonimmediate_operand" "")
- ! (match_operand:XF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
- ***************
- *** 2990,3009 ****
- ;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
-
- ;; ??? What if we only change one byte of an offsettable memory reference?
- (define_insn "andsi3"
- ! [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r")
- ! (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0")
- ! (match_operand:SI 2 "general_operand" "L,K,ri,rm")))]
- ""
- "*
- {
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
- && (! REG_P (operands[1])
- || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
- ! && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1])))
- {
- /* ??? tege: Should forget CC_STATUS only if we clobber a
- remembered operand. Fix that later. */
- --- 2640,2676 ----
- ;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
-
- ;; ??? What if we only change one byte of an offsettable memory reference?
- + ;;(define_insn "andsi3"
- + ;; [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r")
- + ;; (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0")
- + ;; (match_operand:SI 2 "general_operand" "L,K,ri,rm")))]
- + ;; ""
- + ;; "*
- + ;;{
- + ;intel1
- (define_insn "andsi3"
- ! [(set (match_operand:SI 0 "general_operand" "=rm,r,r")
- ! (and:SI (match_operand:SI 1 "general_operand" "0,0,rm")
- ! (match_operand:SI 2 "general_operand" "ri,rm,0")))]
- ""
- "*
- {
- + /* intel1 */
- + if (!rtx_equal_p (operands[0], operands[1])
- + && rtx_equal_p (operands[0], operands[2]))
- + {
- + rtx tmp;
- + tmp = operands[1];
- + operands[1] = operands[2];
- + operands[2] = tmp;
- + }
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
- && (! REG_P (operands[1])
- || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
- ! && (! (TARGET_486 || TARGET_PENTIUM) || ! rtx_equal_p (operands[0], operands[1])))
- {
- /* ??? tege: Should forget CC_STATUS only if we clobber a
- remembered operand. Fix that later. */
- ***************
- *** 3019,3025 ****
- && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
- && (! REG_P (operands[1])
- || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
- ! && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1])))
- {
- /* ??? tege: Should forget CC_STATUS only if we clobber a
- remembered operand. Fix that later. */
- --- 2686,2692 ----
- && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
- && (! REG_P (operands[1])
- || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
- ! && (! (TARGET_486 || TARGET_PENTIUM) || ! rtx_equal_p (operands[0], operands[1])))
- {
- /* ??? tege: Should forget CC_STATUS only if we clobber a
- remembered operand. Fix that later. */
- ***************
- *** 3148,3161 ****
-
- ;;- Bit set (inclusive or) instructions
-
- ;; ??? What if we only change one byte of an offsettable memory reference?
- (define_insn "iorsi3"
- ! [(set (match_operand:SI 0 "general_operand" "=rm,r")
- ! (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
- ! (match_operand:SI 2 "general_operand" "ri,rm")))]
- ""
- "*
- {
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- --- 2815,2837 ----
-
- ;;- Bit set (inclusive or) instructions
-
- + ;intel1 added last constaints
- ;; ??? What if we only change one byte of an offsettable memory reference?
- (define_insn "iorsi3"
- ! [(set (match_operand:SI 0 "general_operand" "=rm,r,r")
- ! (ior:SI (match_operand:SI 1 "general_operand" "%0,0,rm")
- ! (match_operand:SI 2 "general_operand" "ri,rm,0")))]
- ""
- "*
- {
- + /* intel1 */
- + if (!rtx_equal_p (operands[0], operands[1]))
- + {
- + rtx tmp;
- + tmp = operands[1];
- + operands[1] = operands[2];
- + operands[2] = tmp;
- + }
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- ***************
- *** 3185,3197 ****
- return AS2 (or%L0,%2,%0);
- }")
-
- (define_insn "iorhi3"
- ! [(set (match_operand:HI 0 "general_operand" "=rm,r")
- ! (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
- ! (match_operand:HI 2 "general_operand" "ri,rm")))]
- ""
- "*
- {
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- --- 2861,2882 ----
- return AS2 (or%L0,%2,%0);
- }")
-
- + ;intel1 added last constraint
- (define_insn "iorhi3"
- ! [(set (match_operand:HI 0 "general_operand" "=rm,r,r")
- ! (ior:HI (match_operand:HI 1 "general_operand" "%0,0,rm")
- ! (match_operand:HI 2 "general_operand" "ri,rm,0")))]
- ""
- "*
- {
- + /* intel1 */
- + if (!rtx_equal_p (operands[0], operands[1]))
- + {
- + rtx tmp;
- + tmp = operands[1];
- + operands[1] = operands[2];
- + operands[2] = tmp;
- + }
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- ***************
- *** 3227,3238 ****
- return AS2 (or%W0,%2,%0);
- }")
-
- (define_insn "iorqi3"
- ! [(set (match_operand:QI 0 "general_operand" "=qm,q")
- ! (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
- ! (match_operand:QI 2 "general_operand" "qn,qmn")))]
- ""
- ! "* return AS2 (or%B0,%2,%0);")
-
- ;;- xor instructions
-
- --- 2912,2935 ----
- return AS2 (or%W0,%2,%0);
- }")
-
- + ;intel1 added last constraint
- (define_insn "iorqi3"
- ! [(set (match_operand:QI 0 "general_operand" "=qm,q,q")
- ! (ior:QI (match_operand:QI 1 "general_operand" "%0,0,qm")
- ! (match_operand:QI 2 "general_operand" "qn,qmn,0")))]
- ""
- ! "*
- ! {
- ! /* intel1 */
- ! if (!rtx_equal_p (operands[0], operands[1]))
- ! {
- ! rtx tmp;
- ! tmp = operands[1];
- ! operands[1] = operands[2];
- ! operands[2] = tmp;
- ! }
- ! return AS2 (or%B0,%2,%0);
- ! }")
-
- ;;- xor instructions
-
- ***************
- *** 3273,3285 ****
- return AS2 (xor%L0,%2,%0);
- }")
-
- (define_insn "xorhi3"
- ! [(set (match_operand:HI 0 "general_operand" "=rm,r")
- ! (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
- ! (match_operand:HI 2 "general_operand" "ri,rm")))]
- ""
- "*
- {
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- --- 2970,2991 ----
- return AS2 (xor%L0,%2,%0);
- }")
-
- + ;intel1 added last constraint
- (define_insn "xorhi3"
- ! [(set (match_operand:HI 0 "general_operand" "=rm,r,r")
- ! (xor:HI (match_operand:HI 1 "general_operand" "%0,0,rm")
- ! (match_operand:HI 2 "general_operand" "ri,rm,0")))]
- ""
- "*
- {
- + /* intel1 */
- + if (!rtx_equal_p (operands[0], operands[1]))
- + {
- + rtx tmp;
- + tmp = operands[1];
- + operands[1] = operands[2];
- + operands[2] = tmp;
- + }
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- ***************
- *** 3315,3326 ****
- return AS2 (xor%W0,%2,%0);
- }")
-
- (define_insn "xorqi3"
- ! [(set (match_operand:QI 0 "general_operand" "=qm,q")
- ! (xor:QI (match_operand:QI 1 "general_operand" "%0,0")
- ! (match_operand:QI 2 "general_operand" "qn,qm")))]
- ! ""
- ! "* return AS2 (xor%B0,%2,%0);")
-
- ;;- negation instructions
-
- --- 3021,3044 ----
- return AS2 (xor%W0,%2,%0);
- }")
-
- + ;intel1 added last constraint
- (define_insn "xorqi3"
- ! [(set (match_operand:QI 0 "general_operand" "=qm,q,q")
- ! (xor:QI (match_operand:QI 1 "general_operand" "%0,0,qm")
- ! (match_operand:QI 2 "general_operand" "qn,qm,0")))]
- ! ""
- ! "*
- ! {
- ! /* intel1 */
- ! if (!rtx_equal_p (operands[0], operands[1]))
- ! {
- ! rtx tmp;
- ! tmp = operands[1];
- ! operands[1] = operands[2];
- ! operands[2] = tmp;
- ! }
- ! return AS2 (xor%B0,%2,%0);
- ! }")
-
- ;;- negation instructions
-
- ***************
- *** 3382,3394 ****
-
- (define_insn "negxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (neg:XF (match_operand:XF 1 "general_operand" "0")))]
- "TARGET_80387"
- "fchs")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
- "TARGET_80387"
- "fchs")
-
- --- 3100,3112 ----
-
- (define_insn "negxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (neg:XF (match_operand:XF 1 "general_operand" "0")))]
- "TARGET_80387"
- "fchs")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
- "TARGET_80387"
- "fchs")
-
- ***************
- *** 3398,3530 ****
- [(set (match_operand:SF 0 "register_operand" "=f")
- (abs:SF (match_operand:SF 1 "general_operand" "0")))]
- "TARGET_80387"
- ! "fabs")
-
- (define_insn "absdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (match_operand:DF 1 "general_operand" "0")))]
- "TARGET_80387"
- ! "fabs")
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
- "TARGET_80387"
- ! "fabs")
-
- (define_insn "absxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (abs:XF (match_operand:XF 1 "general_operand" "0")))]
- "TARGET_80387"
- ! "fabs")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
- "TARGET_80387"
- ! "fabs")
-
- (define_insn "sqrtsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "general_operand" "0")))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsqrt")
-
- (define_insn "sqrtdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (sqrt:DF (match_operand:DF 1 "general_operand" "0")))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsqrt")
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (sqrt:DF (float_extend:DF
- (match_operand:SF 1 "general_operand" "0"))))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsqrt")
-
- (define_insn "sqrtxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (sqrt:XF (match_operand:XF 1 "general_operand" "0")))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsqrt")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (sqrt:XF (float_extend:XF
- ! (match_operand:DF 1 "general_operand" "0"))))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsqrt")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (sqrt:XF (float_extend:XF
- ! (match_operand:SF 1 "general_operand" "0"))))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsqrt")
-
- (define_insn "sindf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsin")
-
- (define_insn "sinsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsin")
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))] 1))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fsin")
-
- (define_insn "sinxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- "fsin")
-
- (define_insn "cosdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fcos")
-
- (define_insn "cossf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fcos")
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))] 2))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- ! "fcos")
-
- (define_insn "cosxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
- ! "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- ! && (TARGET_IEEE_FP || flag_fast_math) "
- "fcos")
-
- ;;- one complement instructions
- --- 3116,3234 ----
- [(set (match_operand:SF 0 "register_operand" "=f")
- (abs:SF (match_operand:SF 1 "general_operand" "0")))]
- "TARGET_80387"
- ! "fabs"[(set_attr "type" "fpop")])
-
- (define_insn "absdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (match_operand:DF 1 "general_operand" "0")))]
- "TARGET_80387"
- ! "fabs"[(set_attr "type" "fpop")])
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
- "TARGET_80387"
- ! "fabs"[(set_attr "type" "fpop")])
-
- (define_insn "absxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (abs:XF (match_operand:XF 1 "general_operand" "0")))]
- "TARGET_80387"
- ! "fabs"[(set_attr "type" "fpop")])
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
- "TARGET_80387"
- ! "fabs"[(set_attr "type" "fpop")])
-
- (define_insn "sqrtsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "general_operand" "0")))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsqrt"[(set_attr "type" "fpop")])
-
- (define_insn "sqrtdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (sqrt:DF (match_operand:DF 1 "general_operand" "0")))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsqrt"[(set_attr "type" "fpop")])
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (sqrt:DF (float_extend:DF
- (match_operand:SF 1 "general_operand" "0"))))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsqrt"[(set_attr "type" "fpop")])
-
- (define_insn "sqrtxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (sqrt:XF (match_operand:XF 1 "general_operand" "0")))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsqrt"[(set_attr "type" "fpop")])
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (sqrt:XF (float_extend:XF
- ! (match_operand:DF 1 "general_operand" "0"))))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsqrt"[(set_attr "type" "fpop")])
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ! (sqrt:XF (float_extend:XF
- ! (match_operand:SF 1 "general_operand" "0"))))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsqrt"[(set_attr "type" "fpop")])
-
- (define_insn "sindf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsin"[(set_attr "type" "fpop")])
-
- (define_insn "sinsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsin"[(set_attr "type" "fpop")])
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))] 1))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fsin"[(set_attr "type" "fpop")])
-
- (define_insn "sinxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- "fsin")
-
- (define_insn "cosdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fcos"[(set_attr "type" "fpop")])
-
- (define_insn "cossf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fcos"[(set_attr "type" "fpop")])
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))] 2))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- ! "fcos"[(set_attr "type" "fpop")])
-
- (define_insn "cosxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
- ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)"
- "fcos")
-
- ;;- one complement instructions
- ***************
- *** 3676,3682 ****
- {
- if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
- {
- ! if (!TARGET_386 && INTVAL (operands[2]) == 1)
- {
- output_asm_insn (AS2 (mov%L0,%1,%0), operands);
- return AS2 (add%L0,%1,%0);
- --- 3380,3386 ----
- {
- if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
- {
- ! if ((TARGET_486 || TARGET_PENTIUM) && INTVAL (operands[2]) == 1)
- {
- output_asm_insn (AS2 (mov%L0,%1,%0), operands);
- return AS2 (add%L0,%1,%0);
- ***************
- *** 4177,4183 ****
- (const_int 1)
- (match_operand:SI 2 "general_operand" "r"))
- (match_operand:SI 3 "const_int_operand" "n"))]
- ! "TARGET_386 && GET_CODE (operands[2]) != CONST_INT"
- "*
- {
- CC_STATUS_INIT;
- --- 3881,3887 ----
- (const_int 1)
- (match_operand:SI 2 "general_operand" "r"))
- (match_operand:SI 3 "const_int_operand" "n"))]
- ! "! (TARGET_486 || TARGET_PENTIUM) && GET_CODE (operands[2]) != CONST_INT"
- "*
- {
- CC_STATUS_INIT;
- ***************
- *** 4195,4201 ****
- (xor:SI (ashift:SI (const_int 1)
- (match_operand:SI 1 "general_operand" "r"))
- (match_operand:SI 2 "general_operand" "0")))]
- ! "TARGET_386 && GET_CODE (operands[1]) != CONST_INT"
- "*
- {
- CC_STATUS_INIT;
- --- 3899,3905 ----
- (xor:SI (ashift:SI (const_int 1)
- (match_operand:SI 1 "general_operand" "r"))
- (match_operand:SI 2 "general_operand" "0")))]
- ! "! (TARGET_486 || TARGET_PENTIUM) && GET_CODE (operands[1]) != CONST_INT"
- "*
- {
- CC_STATUS_INIT;
- ***************
- *** 4208,4214 ****
- (xor:SI (match_operand:SI 1 "general_operand" "0")
- (ashift:SI (const_int 1)
- (match_operand:SI 2 "general_operand" "r"))))]
- ! "TARGET_386 && GET_CODE (operands[2]) != CONST_INT"
- "*
- {
- CC_STATUS_INIT;
- --- 3912,3918 ----
- (xor:SI (match_operand:SI 1 "general_operand" "0")
- (ashift:SI (const_int 1)
- (match_operand:SI 2 "general_operand" "r"))))]
- ! "! (TARGET_486 || TARGET_PENTIUM) && GET_CODE (operands[2]) != CONST_INT"
- "*
- {
- CC_STATUS_INIT;
- ***************
- *** 4553,4558 ****
- --- 4257,4271 ----
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return \"jnc %l0\";
- else
- + /* intel1 */
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x4000);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (jne,%l0);
- + }
- +
- return \"je %l0\";
- }")
-
- ***************
- *** 4585,4590 ****
- --- 4298,4312 ----
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return \"jc %l0\";
- else
- + /* intel1 */
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x4000);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (je,%l0);
- + }
- +
- return \"jne %l0\";
- }")
-
- ***************
- *** 4610,4615 ****
- --- 4332,4344 ----
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (je,%l0);
-
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x4100);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (je,%l0);
- + }
- OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
- }")
-
- ***************
- *** 4654,4659 ****
- --- 4383,4396 ----
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (je,%l0);
-
- + /* intel1 */
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x100);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (jne,%l0);
- + }
- OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
- }")
-
- ***************
- *** 4697,4703 ****
- {
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (je,%l0);
- !
- OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
- }")
-
- --- 4434,4447 ----
- {
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (je,%l0);
- ! /* intel1 */
- ! if (cc_prev_status.flags & CC_TEST_AX)
- ! {
- ! operands[1] = gen_rtx (REG, SImode, 0);
- ! operands[2] = GEN_INT (0x100);
- ! output_asm_insn (AS2 (testl,%2,%1), operands);
- ! return AS1 (je,%l0);
- ! }
- OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
- }")
-
- ***************
- *** 4741,4746 ****
- --- 4485,4498 ----
- {
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (jb,%l0);
- + /* intel1 */
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x4100);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (jne,%l0);
- + }
-
- OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
- }")
- ***************
- *** 4778,4783 ****
- --- 4530,4543 ----
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return \"jc %l0\";
- else
- + /* intel1 */
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x4000);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (je,%l0);
- + }
- return \"jne %l0\";
- }")
-
- ***************
- *** 4793,4798 ****
- --- 4553,4566 ----
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return \"jnc %l0\";
- else
- + /* intel1 */
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x4000);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (jne,%l0);
- + }
- return \"je %l0\";
- }")
-
- ***************
- *** 4807,4813 ****
- {
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (jne,%l0);
- !
- OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
- }")
-
- --- 4575,4588 ----
- {
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (jne,%l0);
- ! /* intel1 */
- ! if (cc_prev_status.flags & CC_TEST_AX)
- ! {
- ! operands[1] = gen_rtx (REG, SImode, 0);
- ! operands[2] = GEN_INT (0x4100);
- ! output_asm_insn (AS2 (testl,%2,%1), operands);
- ! return AS1 (jne,%l0);
- ! }
- OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
- }")
-
- ***************
- *** 4831,4836 ****
- --- 4606,4619 ----
- {
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (jne,%l0);
- + /* intel1 */
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x100);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (je,%l0);
- + }
-
- OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
- }")
- ***************
- *** 4855,4861 ****
- {
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (jne,%l0);
- !
- OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
- }")
-
- --- 4638,4651 ----
- {
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (jne,%l0);
- ! /* intel1 */
- ! if (cc_prev_status.flags & CC_TEST_AX)
- ! {
- ! operands[1] = gen_rtx (REG, SImode, 0);
- ! operands[2] = GEN_INT (0x100);
- ! output_asm_insn (AS2 (testl,%2,%1), operands);
- ! return AS1 (jne,%l0);
- ! }
- OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
- }")
-
- ***************
- *** 4880,4885 ****
- --- 4670,4683 ----
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
- return AS1 (jae,%l0);
-
- + /* intel1 */
- + if (cc_prev_status.flags & CC_TEST_AX)
- + {
- + operands[1] = gen_rtx (REG, SImode, 0);
- + operands[2] = GEN_INT (0x4100);
- + output_asm_insn (AS2 (testl,%2,%1), operands);
- + return AS1 (je,%l0);
- + }
- OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
- }")
-
- ***************
- *** 5296,5346 ****
- "!HALF_PIC_P ()"
- "call %P1")
-
- - ;; Call subroutine returning any type.
- -
- (define_expand "untyped_call"
- ! [(parallel [(call (match_operand 0 "" "")
- (const_int 0))
- ! (match_operand 1 "" "")
- (match_operand 2 "" "")])]
- ""
- "
- {
- ! int i;
-
- ! /* In order to give reg-stack an easier job in validating two
- ! coprocessor registers as containing a possible return value,
- ! simply pretend the untyped call returns a complex long double
- ! value. */
- ! emit_call_insn (TARGET_80387
- ! ? gen_call_value (gen_rtx (REG, XCmode, FIRST_FLOAT_REG),
- ! operands[0], const0_rtx)
- ! : gen_call (operands[0], const0_rtx));
- !
- ! for (i = 0; i < XVECLEN (operands[2], 0); i++)
- ! {
- ! rtx set = XVECEXP (operands[2], 0, i);
- ! emit_move_insn (SET_DEST (set), SET_SRC (set));
- ! }
- !
- ! /* The optimizer does not know that the call sets the function value
- ! registers we stored in the result block. We avoid problems by
- ! claiming that all hard registers are used and clobbered at this
- ! point. */
- ! emit_insn (gen_blockage ());
-
- ! DONE;
- ! }")
-
- ! ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
- ! ;; all of memory. This blocks insns from being moved across this point.
-
- ! (define_insn "blockage"
- ! [(unspec_volatile [(const_int 0)] 0)]
- ""
- ! "")
-
- ! ;; Insn emitted into the body of a function to return from a function.
- ;; This is only done if the function's epilogue is known to be simple.
- ;; See comments for simple_386_epilogue in i386.c.
-
- --- 5094,5221 ----
- "!HALF_PIC_P ()"
- "call %P1")
-
- (define_expand "untyped_call"
- ! [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
- (const_int 0))
- ! (match_operand:BLK 1 "memory_operand" "")
- (match_operand 2 "" "")])]
- ""
- "
- {
- ! rtx addr;
-
- ! if (flag_pic)
- ! current_function_uses_pic_offset_table = 1;
-
- ! /* With half-pic, force the address into a register. */
- ! addr = XEXP (operands[0], 0);
- ! if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
- ! XEXP (operands[0], 0) = force_reg (Pmode, addr);
-
- ! operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0));
- ! if (! expander_call_insn_operand (operands[1], QImode))
- ! operands[1]
- ! = change_address (operands[1], VOIDmode,
- ! copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
- ! }")
-
- ! (define_insn ""
- ! [(call (match_operand:QI 0 "call_insn_operand" "m")
- ! (const_int 0))
- ! (match_operand:DI 1 "memory_operand" "o")
- ! (match_operand 2 "" "")]
- ""
- ! "*
- ! {
- ! rtx addr = operands[1];
-
- ! if (GET_CODE (operands[0]) == MEM
- ! && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
- ! {
- ! operands[0] = XEXP (operands[0], 0);
- ! output_asm_insn (AS1 (call,%*%0), operands);
- ! }
- ! else
- ! output_asm_insn (AS1 (call,%P0), operands);
- !
- ! operands[2] = gen_rtx (REG, SImode, 0);
- ! output_asm_insn (AS2 (mov%L2,%2,%1), operands);
- !
- ! operands[2] = gen_rtx (REG, SImode, 1);
- ! operands[1] = adj_offsettable_operand (addr, 4);
- ! output_asm_insn (AS2 (mov%L2,%2,%1), operands);
- !
- ! operands[1] = adj_offsettable_operand (addr, 8);
- ! return AS1 (fnsave,%1);
- ! }")
- !
- ! (define_insn ""
- ! [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
- ! (const_int 0))
- ! (match_operand:DI 1 "memory_operand" "o")
- ! (match_operand 2 "" "")]
- ! "!HALF_PIC_P ()"
- ! "*
- ! {
- ! rtx addr = operands[1];
- !
- ! output_asm_insn (AS1 (call,%P0), operands);
- !
- ! operands[2] = gen_rtx (REG, SImode, 0);
- ! output_asm_insn (AS2 (mov%L2,%2,%1), operands);
- !
- ! operands[2] = gen_rtx (REG, SImode, 1);
- ! operands[1] = adj_offsettable_operand (addr, 4);
- ! output_asm_insn (AS2 (mov%L2,%2,%1), operands);
- !
- ! operands[1] = adj_offsettable_operand (addr, 8);
- ! return AS1 (fnsave,%1);
- ! }")
- !
- ! ;; We use fnsave and frstor to save and restore the floating point result.
- ! ;; These are expensive instructions and require a large space to save the
- ! ;; FPU state. An more complicated alternative is to use fnstenv to store
- ! ;; the FPU environment and test whether the stack top is valid. Store the
- ! ;; result of the test, and if it is valid, pop and save the value. The
- ! ;; untyped_return would check the test and optionally push the saved value.
- !
- ! (define_expand "untyped_return"
- ! [(match_operand:BLK 0 "memory_operand" "")
- ! (match_operand 1 "" "")]
- ! ""
- ! "
- ! {
- ! rtx valreg1 = gen_rtx (REG, SImode, 0);
- ! rtx valreg2 = gen_rtx (REG, SImode, 1);
- ! rtx result = operands[0];
- !
- ! /* Restore the FPU state. */
- ! emit_insn (gen_update_return (change_address (result, SImode,
- ! plus_constant (XEXP (result, 0),
- ! 8))));
- !
- ! /* Reload the function value registers. */
- ! emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0)));
- ! emit_move_insn (valreg2,
- ! change_address (result, SImode,
- ! plus_constant (XEXP (result, 0), 4)));
- !
- ! /* Put USE insns before the return. */
- ! emit_insn (gen_rtx (USE, VOIDmode, valreg1));
- ! emit_insn (gen_rtx (USE, VOIDmode, valreg2));
- !
- ! /* Construct the return. */
- ! expand_null_return ();
- !
- ! DONE;
- ! }")
- !
- ! (define_insn "update_return"
- ! [(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)]
- ! ""
- ! "frstor %0")
- !
- ! ;; Insn emitted into the body of a function to return from a function.
- ;; This is only done if the function's epilogue is known to be simple.
- ;; See comments for simple_386_epilogue in i386.c.
-
- ***************
- *** 5387,5393 ****
- ;; It might seem that operands 0 & 1 could use predicate register_operand.
- ;; But strength reduction might offset the MEM expression. So we let
- ;; reload put the address into %edi & %esi.
- !
- (define_insn ""
- [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
- (mem:BLK (match_operand:SI 1 "address_operand" "S")))
- --- 5262,5268 ----
- ;; It might seem that operands 0 & 1 could use predicate register_operand.
- ;; But strength reduction might offset the MEM expression. So we let
- ;; reload put the address into %edi & %esi.
- ! ;; intel1 "e" used to be "S"
- (define_insn ""
- [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
- (mem:BLK (match_operand:SI 1 "address_operand" "S")))
- ***************
- *** 5463,5468 ****
- --- 5338,5344 ----
- ;; possible to know that the length is non-zero, and to avoid the extra
- ;; code to handle zero-length compares.
-
- + ;; intel1 "e" used to be "S"
- (define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=&r")
- (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S"))
- ***************
- *** 5499,5504 ****
- --- 5375,5381 ----
- RET;
- }")
-
- + ;; intel1 "e" used to be "S"
- (define_insn ""
- [(set (cc0)
- (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
- ***************
- *** 5553,5571 ****
- output_asm_insn (AS2 (bsf%L0,%1,%0), xops);
- #ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"jnz %sLFFSSI%d\",
- ! LOCAL_LABEL_PREFIX, ffssi_label_number);
- #else
- sprintf (buffer, \"jnz %sLFFSSI%d\",
- ! \"\", ffssi_label_number);
- #endif
- output_asm_insn (buffer, xops);
- output_asm_insn (AS2 (mov%L0,%2,%0), xops);
- #ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"%sLFFSSI%d:\",
- ! LOCAL_LABEL_PREFIX, ffssi_label_number);
- #else
- sprintf (buffer, \"%sLFFSSI%d:\",
- ! \"\", ffssi_label_number);
- #endif
- output_asm_insn (buffer, xops);
-
- --- 5430,5448 ----
- output_asm_insn (AS2 (bsf%L0,%1,%0), xops);
- #ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"jnz %sLFFSSI%d\",
- ! LOCAL_LABEL_PREFIX, ffssi_label_number);
- #else
- sprintf (buffer, \"jnz %sLFFSSI%d\",
- ! \"\", ffssi_label_number);
- #endif
- output_asm_insn (buffer, xops);
- output_asm_insn (AS2 (mov%L0,%2,%0), xops);
- #ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"%sLFFSSI%d:\",
- ! LOCAL_LABEL_PREFIX, ffssi_label_number);
- #else
- sprintf (buffer, \"%sLFFSSI%d:\",
- ! \"\", ffssi_label_number);
- #endif
- output_asm_insn (buffer, xops);
-
- ***************
- *** 5599,5617 ****
- output_asm_insn (AS2 (bsf%W0,%1,%0), xops);
- #ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"jnz %sLFFSHI%d\",
- ! LOCAL_LABEL_PREFIX, ffshi_label_number);
- #else
- sprintf (buffer, \"jnz %sLFFSHI%d\",
- ! \"\", ffshi_label_number);
- #endif
- output_asm_insn (buffer, xops);
- output_asm_insn (AS2 (mov%W0,%2,%0), xops);
- #ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"%sLFFSHI%d:\",
- ! LOCAL_LABEL_PREFIX, ffshi_label_number);
- #else
- sprintf (buffer, \"%sLFFSHI%d:\",
- ! \"\", ffshi_label_number);
- #endif
- output_asm_insn (buffer, xops);
-
- --- 5476,5494 ----
- output_asm_insn (AS2 (bsf%W0,%1,%0), xops);
- #ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"jnz %sLFFSHI%d\",
- ! LOCAL_LABEL_PREFIX, ffshi_label_number);
- #else
- sprintf (buffer, \"jnz %sLFFSHI%d\",
- ! \"\", ffshi_label_number);
- #endif
- output_asm_insn (buffer, xops);
- output_asm_insn (AS2 (mov%W0,%2,%0), xops);
- #ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"%sLFFSHI%d:\",
- ! LOCAL_LABEL_PREFIX, ffshi_label_number);
- #else
- sprintf (buffer, \"%sLFFSHI%d:\",
- ! \"\", ffshi_label_number);
- #endif
- output_asm_insn (buffer, xops);
-
- ***************
- *** 5626,5639 ****
- ;; the other operand a conversion. The conversion may be SFmode or
- ;; SImode if the target mode DFmode, but only SImode if the target mode
- ;; is SFmode.
- !
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (match_operator:DF 3 "binary_387_op"
- [(match_operand:DF 1 "nonimmediate_operand" "0,fm")
- ! (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- --- 5503,5525 ----
- ;; the other operand a conversion. The conversion may be SFmode or
- ;; SImode if the target mode DFmode, but only SImode if the target mode
- ;; is SFmode.
- ! ;; intel1 2 changed from nonimmediate operand to general operand
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (match_operator:DF 3 "binary_387_op"
- [(match_operand:DF 1 "nonimmediate_operand" "0,fm")
- ! (match_operand:DF 2 "general_operand" "fm,0")]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);"
- ! [(set (attr "type")
- ! (cond [(match_operand:DF 3 "is_mul" "")
- ! (const_string "fpop")
- ! (match_operand:DF 3 "is_div" "")
- ! (const_string "fpdiv")
- ! ]
- ! (const_string "fpop")
- ! )
- ! )])
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- ***************
- *** 5641,5647 ****
- [(float:DF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:DF 2 "general_operand" "0")]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- --- 5527,5533 ----
- [(float:DF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:DF 2 "general_operand" "0")]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- ***************
- *** 5649,5655 ****
- [(match_operand:XF 1 "nonimmediate_operand" "0,f")
- (match_operand:XF 2 "nonimmediate_operand" "f,0")]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- --- 5535,5541 ----
- [(match_operand:XF 1 "nonimmediate_operand" "0,f")
- (match_operand:XF 2 "nonimmediate_operand" "f,0")]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ***************
- *** 5657,5663 ****
- [(float:XF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:XF 2 "general_operand" "0")]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- --- 5543,5549 ----
- [(float:XF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:XF 2 "general_operand" "0")]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- ***************
- *** 5665,5671 ****
- [(float_extend:XF (match_operand:SF 1 "general_operand" "fm,0"))
- (match_operand:XF 2 "general_operand" "0,f")]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- --- 5551,5557 ----
- [(float_extend:XF (match_operand:SF 1 "general_operand" "fm,0"))
- (match_operand:XF 2 "general_operand" "0,f")]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- ***************
- *** 5673,5679 ****
- [(match_operand:XF 1 "general_operand" "0")
- (float:XF (match_operand:SI 2 "general_operand" "rm"))]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- --- 5559,5565 ----
- [(match_operand:XF 1 "general_operand" "0")
- (float:XF (match_operand:SI 2 "general_operand" "rm"))]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f,f")
- ***************
- *** 5681,5688 ****
- [(match_operand:XF 1 "general_operand" "0,f")
- (float_extend:XF
- (match_operand:SF 2 "general_operand" "fm,0"))]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- --- 5567,5584 ----
- [(match_operand:XF 1 "general_operand" "0,f")
- (float_extend:XF
- (match_operand:SF 2 "general_operand" "fm,0"))]))]
- +
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);"
- ! [(set (attr "type")
- ! (cond [(match_operand:DF 3 "is_mul" "")
- ! (const_string "fpop")
- ! (match_operand:DF 3 "is_div" "")
- ! (const_string "fpdiv")
- ! ]
- ! (const_string "fpop")
- ! )
- ! )])
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- ***************
- *** 5690,5696 ****
- [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0"))
- (match_operand:DF 2 "general_operand" "0,f")]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- --- 5586,5601 ----
- [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0"))
- (match_operand:DF 2 "general_operand" "0,f")]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);"
- ! [(set (attr "type")
- ! (cond [(match_operand:DF 3 "is_mul" "")
- ! (const_string "fpop")
- ! (match_operand:DF 3 "is_div" "")
- ! (const_string "fpdiv")
- ! ]
- ! (const_string "fpop")
- ! )
- ! )])
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- ***************
- *** 5698,5704 ****
- [(match_operand:DF 1 "general_operand" "0")
- (float:DF (match_operand:SI 2 "general_operand" "rm"))]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- --- 5603,5618 ----
- [(match_operand:DF 1 "general_operand" "0")
- (float:DF (match_operand:SI 2 "general_operand" "rm"))]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);"
- ! [(set (attr "type")
- ! (cond [(match_operand:DF 3 "is_mul" "")
- ! (const_string "fpop")
- ! (match_operand:DF 3 "is_div" "")
- ! (const_string "fpdiv")
- ! ]
- ! (const_string "fpop")
- ! )
- ! )])
-
- (define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- ***************
- *** 5707,5721 ****
- (float_extend:DF
- (match_operand:SF 2 "general_operand" "fm,0"))]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (match_operator:SF 3 "binary_387_op"
- ! [(match_operand:SF 1 "nonimmediate_operand" "0,fm")
- ! (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- --- 5621,5654 ----
- (float_extend:DF
- (match_operand:SF 2 "general_operand" "fm,0"))]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);"
- ! [(set (attr "type")
- ! (cond [(match_operand:DF 3 "is_mul" "")
- ! (const_string "fpop")
- ! (match_operand:DF 3 "is_div" "")
- ! (const_string "fpdiv")
- ! ]
- ! (const_string "fpop")
- ! )
- ! )])
-
- + ;; intel1 1 and 2 changed from nonimmediate operand to general operand
- (define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (match_operator:SF 3 "binary_387_op"
- ! [(match_operand:SF 1 "general_operand" "0,fm")
- ! (match_operand:SF 2 "general_operand" "fm,0")]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);"
- ! [(set (attr "type")
- ! (cond [(match_operand:DF 3 "is_mul" "")
- ! (const_string "fpop")
- ! (match_operand:DF 3 "is_div" "")
- ! (const_string "fpdiv")
- ! ]
- ! (const_string "fpop")
- ! )
- ! )])
-
- (define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- ***************
- *** 5723,5729 ****
- [(float:SF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:SF 2 "general_operand" "0")]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- --- 5656,5671 ----
- [(float:SF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:SF 2 "general_operand" "0")]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);"
- ! [(set (attr "type")
- ! (cond [(match_operand:DF 3 "is_mul" "")
- ! (const_string "fpop")
- ! (match_operand:DF 3 "is_div" "")
- ! (const_string "fpdiv")
- ! ]
- ! (const_string "fpop")
- ! )
- ! )])
-
- (define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- ***************
- *** 5731,5737 ****
- [(match_operand:SF 1 "general_operand" "0")
- (float:SF (match_operand:SI 2 "general_operand" "rm"))]))]
- "TARGET_80387"
- ! "* return output_387_binary_op (insn, operands);")
-
- (define_expand "strlensi"
- [(parallel [(set (match_dup 4)
- --- 5673,5688 ----
- [(match_operand:SF 1 "general_operand" "0")
- (float:SF (match_operand:SI 2 "general_operand" "rm"))]))]
- "TARGET_80387"
- ! "* return (char *) output_387_binary_op (insn, operands);"
- ! [(set (attr "type")
- ! (cond [(match_operand:DF 3 "is_mul" "")
- ! (const_string "fpop")
- ! (match_operand:DF 3 "is_div" "")
- ! (const_string "fpdiv")
- ! ]
- ! (const_string "fpop")
- ! )
- ! )])
-
- (define_expand "strlensi"
- [(parallel [(set (match_dup 4)
- ***************
- *** 5773,5775 ****
- --- 5724,6535 ----
- output_asm_insn (AS2 (mov%L0,%1,%0), xops);
- return \"repnz\;scas%B2\";
- }")
- +
- + ;; intel1 peepholes
- + ;; change fstp mem1
- + ;; fld mem1
- + ;; fop mem2
- + ;; to
- + ;; fst mem1
- + ;; fop mem2
- +
- + (define_peephole
- + [(set (match_operand:DF 0 "memory_operand" "g")
- + (reg:DF 8))
- + (set (reg:DF 8)
- + (match_operand:DF 1 "memory_operand" "g"))
- + (set (reg:DF 8)
- + (mult:DF (reg:DF 8)
- + (match_dup 0)))
- + ]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if (flag_float_store)
- + {
- + output_asm_insn (AS1 (fstpl,%0),operands);
- + output_asm_insn (AS1 (fldl,%1),operands);
- + return AS1(fmull,%0);
- + }
- + output_asm_insn (AS1 (fstl,%0),operands);
- + return AS1(fmull,%1);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fstl,%0),operands);
- + output_asm_insn (AS1 (fldl,%1),operands);
- + return AS1(fmull,%0);
- + }
- + }"
- + );
- +
- +
- +
- + (define_peephole
- + [(set (match_operand:DF 0 "memory_operand" "g")
- + (reg:DF 8))
- + (set (reg:DF 8)
- + (match_operand:DF 1 "memory_operand" "g"))
- + (set (reg:DF 8)
- + (plus:DF (reg:DF 8)
- + (match_dup 0)))
- + ]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if (flag_float_store)
- + {
- + output_asm_insn (AS1 (fstpl,%0),operands);
- + output_asm_insn (AS1 (fldl,%1),operands);
- + return AS1(faddl,%0);
- + }
- + output_asm_insn (AS1 (fstl,%0),operands);
- + return AS1(faddl,%1);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fstl,%0),operands);
- + output_asm_insn (AS1 (fldl,%1),operands);
- + return AS1(faddl,%0);
- + }
- + }"
- + );
- +
- +
- +
- + (define_peephole
- + [(set (match_operand:DF 0 "memory_operand" "g")
- + (reg:DF 8))
- + (set (reg:DF 8)
- + (match_operand:DF 1 "memory_operand" "g"))
- + (set (reg:DF 8)
- + (minus:DF (reg:DF 8)
- + (match_dup 0)))
- + ]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if (flag_float_store)
- + {
- + output_asm_insn (AS1 (fstpl,%0),operands);
- + output_asm_insn (AS1 (fldl,%1),operands);
- + return AS1(fsubl,%0);
- + }
- + output_asm_insn (AS1 (fstl,%0),operands);
- + return AS1(fsubrl,%1);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fstl,%0),operands);
- + output_asm_insn (AS1 (fldl,%1),operands);
- + return AS1(fsubl,%0);
- + }
- + }"
- + );
- +
- +
- +
- + (define_peephole
- + [(set (match_operand:DF 0 "memory_operand" "g")
- + (reg:DF 8))
- + (set (reg:DF 8)
- + (match_operand:DF 1 "memory_operand" "g"))
- + (set (reg:DF 8)
- + (div:DF (reg:DF 8)
- + (match_dup 0)))
- + ]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if (flag_float_store)
- + {
- + output_asm_insn (AS1 (fstpl,%0),operands);
- + output_asm_insn (AS1 (fldl,%1),operands);
- + return AS1(fdivl,%0);
- + }
- + output_asm_insn (AS1 (fstl,%0),operands);
- + return AS1(fdivrl,%1);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fstl,%0),operands);
- + output_asm_insn (AS1 (fldl,%1),operands);
- + return AS1(fdivl,%0);
- + }
- + }"
- + );
- +
- +
- + (define_peephole
- + [(set (match_operand:SF 0 "memory_operand" "g")
- + (reg:SF 8))
- + (set (reg:SF 8)
- + (match_operand:SF 1 "memory_operand" "g"))
- + (set (reg:SF 8)
- + (mult:SF (reg:SF 8)
- + (match_dup 0)))
- + ]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if (flag_float_store)
- + {
- + output_asm_insn (AS1 (fstps,%0),operands);
- + output_asm_insn (AS1 (flds,%1),operands);
- + return AS1(fmuls,%0);
- + }
- + output_asm_insn (AS1 (fsts,%0),operands);
- + return AS1(fmuls,%1);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fsts,%0),operands);
- + output_asm_insn (AS1 (flds,%1),operands);
- + return AS1(fmuls,%0);
- + }
- + }"
- + );
- +
- +
- +
- + (define_peephole
- + [(set (match_operand:SF 0 "memory_operand" "g")
- + (reg:SF 8))
- + (set (reg:SF 8)
- + (match_operand:SF 1 "memory_operand" "g"))
- + (set (reg:SF 8)
- + (plus:SF (reg:SF 8)
- + (match_dup 0)))
- + ]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if (flag_float_store)
- + {
- + output_asm_insn (AS1 (fstps,%0),operands);
- + output_asm_insn (AS1 (flds,%1),operands);
- + return AS1(fadds,%0);
- + }
- + output_asm_insn (AS1 (fsts,%0),operands);
- + return AS1(fadds,%1);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fsts,%0),operands);
- + output_asm_insn (AS1 (flds,%1),operands);
- + return AS1(fadds,%0);
- + }
- + }"
- + );
- +
- +
- +
- + (define_peephole
- + [(set (match_operand:SF 0 "memory_operand" "g")
- + (reg:SF 8))
- + (set (reg:SF 8)
- + (match_operand:SF 1 "memory_operand" "g"))
- + (set (reg:SF 8)
- + (minus:SF (reg:SF 8)
- + (match_dup 0)))
- + ]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if (flag_float_store)
- + {
- + output_asm_insn (AS1 (fstps,%0),operands);
- + output_asm_insn (AS1 (flds,%1),operands);
- + return AS1(fsubs,%0);
- + }
- + output_asm_insn (AS1 (fsts,%0),operands);
- + return AS1(fsubrs,%1);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fsts,%0),operands);
- + output_asm_insn (AS1 (flds,%1),operands);
- + return AS1(fsubs,%0);
- + }
- + }"
- + );
- +
- +
- +
- + (define_peephole
- + [(set (match_operand:SF 0 "memory_operand" "g")
- + (reg:SF 8))
- + (set (reg:SF 8)
- + (match_operand:SF 1 "memory_operand" "g"))
- + (set (reg:SF 8)
- + (div:SF (reg:SF 8)
- + (match_dup 0)))
- + ]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if (flag_float_store)
- + {
- + output_asm_insn (AS1 (fstps,%0),operands);
- + output_asm_insn (AS1 (flds,%1),operands);
- + return AS1(fdivs,%0);
- + }
- + output_asm_insn (AS1 (fsts,%0),operands);
- + return AS1(fdivrs,%1);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fsts,%0),operands);
- + output_asm_insn (AS1 (flds,%1),operands);
- + return AS1(fdivs,%0);
- + }
- + }"
- + );
- +
- +
- + ;; change fstp mem1
- + ;; fld mem1
- + ;; to
- + ;; fst mem1
- +
- + (define_peephole
- + [(set (match_operand:DF 0 "memory_operand" "g")
- + (reg:DF 8))
- + (set (reg:DF 8)
- + (match_dup 0))]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if(!MEM_VOLATILE_P (operands[0]) && !flag_float_store)
- + {
- + return AS1 (fstl,%0);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fstpl,%0),operands);
- + return AS1 (fldl,%0);
- + }
- + }
- + else
- + {
- + output_asm_insn (AS1 (fstl,%0),operands);
- + return AS1 (fldl,%0);
- + }
- + }"
- + );
- +
- + (define_peephole
- + [(set (match_operand:SF 0 "memory_operand" "g")
- + (reg:SF 8))
- + (set (reg:SF 8)
- + (match_dup 0))]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- + {
- + if(!MEM_VOLATILE_P (operands[0]) && !flag_float_store)
- + {
- + return AS1 (fsts,%0);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fstps,%0),operands);
- + return AS1 (flds,%0);
- + }
- + }
- + else
- + {
- + output_asm_insn (AS1 (fsts,%0),operands);
- + return AS1 (flds,%0);
- + }
- + }"
- + );
- +
- + (define_peephole
- + [(set (match_operand:SF 0 "memory_operand" "g")
- + (reg:SF 8))
- + (set (reg:DF 8)
- + (float_extend:DF (match_dup 0)))]
- + "TARGET_80387"
- + "*
- + {
- + extern int flag_float_store;
- + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) && !flag_float_store)
- + {
- + return AS1 (fsts,%0);
- + }
- + else
- + {
- + output_asm_insn (AS1 (fsts,%0),operands);
- + return AS1 (flds,%0);
- + }
- + }"
- + );
- +
- + ;; see if compare can be deleted
- + (define_peephole
- + [
- + (set (cc0)
- + (compare (const_int 0)
- + (match_operand:SI 0 "general_operand" "g")))
- + (set (pc)
- + (if_then_else (ne (cc0)
- + (const_int 0))
- + (label_ref (match_operand 1 "" ""))
- + (pc)))
- + ]
- + ""
- + "*
- + {
- + if(!last_to_set_cc(operands[0]),insn)
- + {
- + operands[2] = const0_rtx;
- + output_asm_insn (AS2 (cmp%L0,%2,%0),operands);
- + return \"jne %l1\";
- + }
- + else
- + {
- + return \"jne %l1\";
- + }
- + }");
- +
- + (define_peephole
- + [
- + (set (cc0)
- + (compare (match_operand:SI 0 "general_operand" "g")
- + (const_int 0)))
- + (set (pc)
- + (if_then_else (ne (cc0)
- + (const_int 0))
- + (label_ref (match_operand 1 "" ""))
- + (pc)))
- + ]
- + ""
- + "*
- + {
- + if(!last_to_set_cc(operands[0],insn))
- + {
- + operands[2] = const0_rtx;
- + output_asm_insn (AS2 (cmp%L0,%2,%0),operands);
- + return \"jne %l1\";
- + }
- + else
- + {
- + return \"jne %l1\";
- + }
- + }");
- +
- + ;; optimization of sign_extend combined with and
- + (define_peephole
- + [
- + (set (match_operand:HI 0 "register_operand" "")
- + (and:HI (match_dup 0)
- + (match_operand:HI 1 "immediate_operand" "")))
- + (set (match_operand:SI 2 "register_operand" "")
- + (sign_extend:SI
- + (match_dup 0)))
- + ]
- + ""
- + "*
- + {
- + int no_sign_extend = 0;
- + rtx note;
- + if ((INTVAL (operands[1]) & 0x8000) == 0)
- + { /* Don't need to do sign extend */
- + no_sign_extend = 1;
- + }
- + CC_STATUS_INIT;
- + if (no_sign_extend)
- + {
- + if (REGNO (operands[0]) == REGNO (operands[2]))
- + {
- + operands [0] = gen_rtx (REG, SImode, REGNO (operands[0]));
- + output_asm_insn (AS2 (and%L0,%1,%0), operands);
- + }
- + else
- + {
- + output_asm_insn (AS2 (and%W0,%1,%w0), operands);
- + operands [0] = gen_rtx (REG, SImode, REGNO (operands[0]));
- + output_asm_insn (AS2 (mov%L0,%0,%2), operands);
- + operands [1] = gen_rtx (CONST_INT, 0, 0xffff);
- + output_asm_insn (AS2 (and%L0,%1,%2), operands);
- + }
- + RET;
- + }
- + /* Can we ignore the upper byte? */
- + else if (QI_REG_P (operands[0])
- + && (INTVAL (operands[1]) & 0xff00) == 0xff00)
- + {
- + if ((INTVAL (operands[1]) & 0xff) == 0)
- + {
- + operands[1] = const0_rtx;
- + output_asm_insn (AS2 (mov%B0,%1,%b0), operands);
- + }
- + else
- + {
- + operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
- + output_asm_insn (AS2 (and%B0,%1,%b0), operands);
- + }
- + }
- + else if (!no_sign_extend && QI_REG_P (operands[0])
- + && (INTVAL (operands[1]) & 0xff) == 0xff)
- + {
- + if ((INTVAL (operands[1]) & 0xff00) == 0)
- + {
- + operands[1] = const0_rtx;
- + output_asm_insn (AS2 (mov%B0,%1,%h0), operands);
- + }
- +
- + operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff);
- + output_asm_insn (AS2 (and%B0,%1,%b0), operands);
- + }
- + if (REGNO (operands[2]) == 0 && REGNO (operands[0]) == 0)
- + #ifdef INTEL_SYNTAX
- + return \"cwde\";
- + #else
- + return \"cwtl\";
- + #endif
- +
- + #ifdef INTEL_SYNTAX
- + return AS2 (movsx,%0,%2);
- + #else
- + return AS2 (movs%W0%L0,%0,%2);
- + #endif
- + }");
- +
- + (define_peephole
- + [
- + (set (match_operand:HI 0 "register_operand" "")
- + (match_operand:HI 1 "memory_operand" ""))
- + (set (match_dup 0)
- + (and:HI (match_dup 0)
- + (match_operand:HI 2 "immediate_operand" "")))
- + (set (match_operand:SI 3 "register_operand" "")
- + (sign_extend:SI
- + (match_dup 0)))
- + ]
- + ""
- + "*
- + {
- + int no_sign_extend = 0;
- + if ((INTVAL (operands[2]) & 0xff00) == 0
- + && QI_REG_P (operands[0]))
- + {
- + output_asm_insn (AS2 (mov%B0,%b1,%b0), operands);
- + }
- + else
- + {
- + output_asm_insn (AS2 (mov%W0,%1,%0), operands);
- + }
- + if ((INTVAL (operands[2]) & 0x8000) == 0)
- + { /* Don't need to do sign extend */
- + no_sign_extend = 1;
- + }
- + CC_STATUS_INIT;
- + if (no_sign_extend)
- + {
- + if (REGNO (operands[0]) == REGNO (operands[3]))
- + {
- + operands [0] = gen_rtx (REG, SImode, REGNO (operands[0]));
- + output_asm_insn (AS2 (and%L0,%2,%0), operands);
- + }
- + else
- + {
- + output_asm_insn (AS2 (and%W0,%2,%w0), operands);
- + operands [0] = gen_rtx (REG, SImode, REGNO (operands[0]));
- + output_asm_insn (AS2 (mov%L0,%0,%3), operands);
- + operands [2] = gen_rtx (CONST_INT, 0, 0xffff);
- + output_asm_insn (AS2 (and%L0,%2,%3), operands);
- + }
- + RET;
- + }
- + /* Can we ignore the upper byte? */
- + else if (QI_REG_P (operands[0])
- + && (INTVAL (operands[2]) & 0xff00) == 0xff00)
- + {
- + if ((INTVAL (operands[2]) & 0xff) == 0)
- + {
- + operands[2] = const0_rtx;
- + output_asm_insn (AS2 (mov%B0,%2,%b0), operands);
- + }
- + else
- + {
- + operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
- + output_asm_insn (AS2 (and%B0,%2,%b0), operands);
- + }
- + }
- + else if (!no_sign_extend && QI_REG_P (operands[0])
- + && (INTVAL (operands[2]) & 0xff) == 0xff)
- + {
- + if ((INTVAL (operands[2]) & 0xff00) == 0)
- + {
- + operands[2] = const0_rtx;
- + output_asm_insn (AS2 (mov%B0,%2,%h0), operands);
- + }
- +
- + operands[1] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
- + output_asm_insn (AS2 (and%B0,%2,%b0), operands);
- + }
- + else
- + {
- + output_asm_insn (AS2 (and%W0,%2,%0), operands);
- + }
- + if (REGNO (operands[3]) == 0 && REGNO (operands[0]) == 0)
- + #ifdef INTEL_SYNTAX
- + return \"cwde\";
- + #else
- + return \"cwtl\";
- + #endif
- +
- + #ifdef INTEL_SYNTAX
- + return AS2 (movsx,%0,%3);
- + #else
- + return AS2 (movs%W0%L0,%0,%3);
- + #endif
- + }");
- +
- + (define_peephole
- + [
- + (set (match_operand:HI 0 "register_operand" "")
- + (sign_extend:HI
- + (match_operand:QI 1 "memory_operand" "")))
- + (set (match_dup 0)
- + (and:HI (match_dup 0)
- + (match_operand:HI 2 "immediate_operand" "")))
- + (set (match_operand:SI 3 "register_operand" "")
- + (sign_extend:SI
- + (match_dup 0)))
- + ]
- + ""
- + "*
- + {
- + int no_sign_extend = 0;
- + if ((INTVAL (operands[2]) & 0xff00) == 0
- + && QI_REG_P (operands[0]))
- + {
- + output_asm_insn (AS2 (mov%B0,%b1,%b0), operands);
- + }
- + else
- + {
- + #ifdef INTEL_SYNTAX
- + output_asm_insn( AS2 (movsx,%1,%0), operands);
- + #else
- + output_asm_insn( AS2 (movs%B0%W0,%1,%0), operands);
- + #endif
- + }
- + if ((INTVAL (operands[2]) & 0x8000) == 0)
- + { /* Don't need to do sign extend */
- + no_sign_extend = 1;
- + }
- + CC_STATUS_INIT;
- + if (no_sign_extend)
- + {
- + if (REGNO (operands[0]) == REGNO (operands[3]))
- + {
- + operands [0] = gen_rtx (REG, SImode, REGNO (operands[0]));
- + output_asm_insn (AS2 (and%L0,%2,%0), operands);
- + }
- + else
- + {
- + output_asm_insn (AS2 (and%W0,%2,%w0), operands);
- + operands [0] = gen_rtx (REG, SImode, REGNO (operands[0]));
- + output_asm_insn (AS2 (mov%L0,%0,%3), operands);
- + operands [2] = gen_rtx (CONST_INT, 0, 0xffff);
- + output_asm_insn (AS2 (and%L0,%2,%3), operands);
- + }
- + RET;
- + }
- + /* Can we ignore the upper byte? */
- + else if (QI_REG_P (operands[0])
- + && (INTVAL (operands[2]) & 0xff00) == 0xff00)
- + {
- + if ((INTVAL (operands[2]) & 0xff) == 0)
- + {
- + operands[2] = const0_rtx;
- + output_asm_insn (AS2 (mov%B0,%2,%b0), operands);
- + }
- + else
- + {
- + operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
- + output_asm_insn (AS2 (and%B0,%2,%b0), operands);
- + }
- + }
- + else if (!no_sign_extend && QI_REG_P (operands[0])
- + && (INTVAL (operands[2]) & 0xff) == 0xff)
- + {
- + if ((INTVAL (operands[2]) & 0xff00) == 0)
- + {
- + operands[2] = const0_rtx;
- + output_asm_insn (AS2 (mov%B0,%2,%h0), operands);
- + }
- +
- + operands[1] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
- + output_asm_insn (AS2 (and%B0,%2,%b0), operands);
- + }
- + else
- + {
- + output_asm_insn (AS2 (and%W0,%2,%0), operands);
- + }
- + if (REGNO (operands[3]) == 0 && REGNO (operands[0]) == 0)
- + #ifdef INTEL_SYNTAX
- + return \"cwde\";
- + #else
- + return \"cwtl\";
- + #endif
- +
- + #ifdef INTEL_SYNTAX
- + return AS2 (movsx,%0,%3);
- + #else
- + return AS2 (movs%W0%L0,%0,%3);
- + #endif
- + }");
- +
- + (define_peephole
- + [
- + (set (match_operand:HI 0 "register_operand" "")
- + (sign_extend:HI
- + (match_operand:QI 1 "memory_operand" "")))
- + (set (match_dup 0)
- + (and:HI (match_dup 0)
- + (match_operand:HI 2 "immediate_operand" "")))
- + ]
- + ""
- + "*
- + {
- + if ((INTVAL (operands[2]) & 0xff00) == 0
- + && QI_REG_P (operands[0]))
- + {
- + output_asm_insn (AS2 (mov%B0,%b1,%b0), operands);
- + }
- + else
- + {
- + #ifdef INTEL_SYNTAX
- + output_asm_insn( AS2 (movsx,%1,%0), operands);
- + #else
- + output_asm_insn( AS2 (movs%B0%W0,%1,%0), operands);
- + #endif
- + }
- + /* Can we ignore the upper byte? */
- + if (QI_REG_P (operands[0])
- + && (INTVAL (operands[2]) & 0xff00) == 0xff00)
- + {
- + if ((INTVAL (operands[2]) & 0xff) == 0)
- + {
- + operands[2] = const0_rtx;
- + output_asm_insn (AS2 (mov%B0,%2,%b0), operands);
- + }
- + else
- + {
- + operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
- + output_asm_insn (AS2 (and%B0,%2,%b0), operands);
- + }
- + }
- + else if (QI_REG_P (operands[0])
- + && (INTVAL (operands[2]) & 0xff) == 0xff)
- + {
- + if ((INTVAL (operands[2]) & 0xff00) == 0)
- + {
- + operands[2] = const0_rtx;
- + output_asm_insn (AS2 (mov%B0,%2,%h0), operands);
- + }
- +
- + operands[1] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
- + output_asm_insn (AS2 (and%B0,%2,%b0), operands);
- + }
- + else
- + {
- + output_asm_insn (AS2 (and%W0,%2,%0), operands);
- + }
- + RET;
- + }");
- +
- + (define_peephole
- + [
- + (set (match_operand:SI 0 "register_operand" "")
- + (sign_extend:SI
- + (match_operand:QI 1 "memory_operand" "")))
- + (set (match_dup 0)
- + (and:SI (match_dup 0)
- + (match_operand:SI 2 "immediate_operand" "")))
- + ]
- + ""
- + "*
- + {
- + if ((INTVAL (operands[2]) & 0xffffff00) == 0
- + && QI_REG_P (operands[0]))
- + {
- + output_asm_insn (AS2 (mov%B0,%b1,%b0), operands);
- + }
- + else
- + {
- + #ifdef INTEL_SYNTAX
- + output_asm_insn( AS2 (movsx,%1,%0), operands);
- + #else
- + output_asm_insn( AS2 (movs%B0%L0,%1,%0), operands);
- + #endif
- + }
- + output_asm_insn (AS2 (and%L0,%2,%0), operands);
- + RET;
- + }");
- +
- + (define_peephole
- + [
- + (set (match_operand:SI 0 "register_operand" "")
- + (sign_extend:SI
- + (match_operand:HI 1 "memory_operand" "")))
- + (set (match_dup 0)
- + (and:SI (match_dup 0)
- + (match_operand:SI 2 "immediate_operand" "")))
- + ]
- + ""
- + "*
- + {
- + if ((INTVAL (operands[2]) & 0xffffff00) == 0
- + && QI_REG_P (operands[0]))
- + {
- + output_asm_insn (AS2 (mov%B0,%b1,%b0), operands);
- + }
- + else if ((INTVAL (operands[2]) & 0xffff0000) == 0)
- + {
- + output_asm_insn (AS2 (mov%W0,%h1,%h0), operands);
- + }
- + else
- + {
- + #ifdef INTEL_SYNTAX
- + output_asm_insn( AS2 (movsx,%1,%0), operands);
- + #else
- + output_asm_insn( AS2 (movs%B0%W0,%1,%0), operands);
- + #endif
- + }
- + output_asm_insn (AS2 (and%L0,%2,%0), operands);
- + RET;
- + }");
- diff -rNci gcc-2.7.2/config.sub gcc-2.7.2p/config.sub
- *** gcc-2.7.2/config.sub Thu Jun 15 21:01:49 1995
- --- gcc-2.7.2p/config.sub Tue Jan 23 09:25:24 1996
- ***************
- *** 130,141 ****
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm \
- ! | arme[lb] | pyramid \
- | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
- | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \
- | powerpc | powerpcle | sparc64 | 1750a | dsp16xx | mips64 | mipsel \
- | pdp11 | mips64el | mips64orion | mips64orionel \
- ! | sparc)
- basic_machine=$basic_machine-unknown
- ;;
- # Object if more than one company name word.
- --- 130,141 ----
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm \
- ! | pentium | arme[lb] | pyramid \
- | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
- | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \
- | powerpc | powerpcle | sparc64 | 1750a | dsp16xx | mips64 | mipsel \
- | pdp11 | mips64el | mips64orion | mips64orionel \
- ! | sparc )
- basic_machine=$basic_machine-unknown
- ;;
- # Object if more than one company name word.
- ***************
- *** 145,157 ****
- ;;
- # Recognize the basic CPU types with company name.
- vax-* | tahoe-* | i[345]86-* | i860-* | m68k-* | m68000-* | m88k-* \
- ! | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
- | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
- | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
- | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
- | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
- | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
- ! | mips64el-* | mips64orion-* | mips64orionel-*)
- ;;
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- --- 145,157 ----
- ;;
- # Recognize the basic CPU types with company name.
- vax-* | tahoe-* | i[345]86-* | i860-* | m68k-* | m68000-* | m88k-* \
- ! | pentium-* | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
- | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
- | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
- | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
- | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
- | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
- ! | mips64el-* | mips64orion-* | mips64orionel-* )
- ;;
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- ***************
- *** 312,329 ****
- --- 312,345 ----
- basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
- os=-sysv32
- ;;
- + pentiumv32)
- + basic_machine=`echo $1 | sed -e 's/pentium.*/pentium-unknown/'`
- + os=-sysv32
- + ;;
- i[345]86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
- os=-sysv4
- ;;
- + pentiumv4*)
- + basic_machine=`echo $1 | sed -e 's/pentium.*/pentium-unknown/'`
- + os=-sysv4
- + ;;
- i[345]86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
- os=-sysv
- ;;
- + pentiumv)
- + basic_machine=`echo $1 | sed -e 's/pentium.*/pentium-unknown/'`
- + os=-sysv
- + ;;
- i[345]86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
- os=-solaris2
- ;;
- + pentiumsol2)
- + basic_machine=`echo $1 | sed -e 's/pentium.*/pentium-unknown/'`
- + os=-solaris2
- + ;;
- iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- diff -rNci gcc-2.7.2/configure gcc-2.7.2p/configure
- *** gcc-2.7.2/configure Sun Nov 26 19:39:15 1995
- --- gcc-2.7.2p/configure Tue Jan 23 09:53:19 1996
- ***************
- *** 844,850 ****
- xm_file=i370/xm-mvs.h
- out_file=i370/mvs370.c
- ;;
- ! i[345]86-ibm-aix*) # IBM PS/2 running AIX
- cpu_type=i386
- if [ x$gas = xyes ]
- then
- --- 844,850 ----
- xm_file=i370/xm-mvs.h
- out_file=i370/mvs370.c
- ;;
- ! pentium-ibm-aix* | i[345]86-ibm-aix*) # IBM PS/2 running AIX
- cpu_type=i386
- if [ x$gas = xyes ]
- then
- ***************
- *** 867,873 ****
- extra_parts="crtbegin.o crtend.o"
- tmake_file=i386/t-crtpic
- ;;
- ! i[345]86-next-*)
- cpu_type=i386
- tm_file=i386/next.h
- out_file=i386/next.c
- --- 867,873 ----
- extra_parts="crtbegin.o crtend.o"
- tmake_file=i386/t-crtpic
- ;;
- ! pentium-next-* | i[345]86-next-*)
- cpu_type=i386
- tm_file=i386/next.h
- out_file=i386/next.c
- ***************
- *** 875,881 ****
- tmake_file=i386/t-next
- xmake_file=i386/x-next
- ;;
- ! i[345]86-sequent-bsd*) # 80386 from Sequent
- cpu_type=i386
- use_collect2=yes
- if [ x$gas = xyes ]
- --- 875,881 ----
- tmake_file=i386/t-next
- xmake_file=i386/x-next
- ;;
- ! pentium-sequent-bsd* | i[345]86-sequent-bsd*) # 80386 from Sequent
- cpu_type=i386
- use_collect2=yes
- if [ x$gas = xyes ]
- ***************
- *** 885,891 ****
- tm_file=i386/sequent.h
- fi
- ;;
- ! i[345]86-sequent-ptx1*)
- cpu_type=i386
- xm_file=i386/xm-sysv3.h
- xmake_file=i386/x-sysv3
- --- 885,891 ----
- tm_file=i386/sequent.h
- fi
- ;;
- ! pentium-sequent-ptx1* | i[345]86-sequent-ptx1*)
- cpu_type=i386
- xm_file=i386/xm-sysv3.h
- xmake_file=i386/x-sysv3
- ***************
- *** 912,928 ****
- tm_file=i386/sun.h
- use_collect2=yes
- ;;
- i[345]86-*-aout*)
- cpu_type=i386
- tm_file=i386/i386-aout.h
- tmake_file=i386/t-i386bare
- ;;
- - i[345]86-*-bsdi* | i[345]86-*-bsd386*)
- - cpu_type=i386
- - tm_file=i386/bsd386.h
- - xm_file=i386/xm-bsd386.h
- - # tmake_file=t-libc-ok
- - ;;
- i[345]86-*-bsd*)
- cpu_type=i386
- tm_file=i386/386bsd.h
- --- 912,927 ----
- tm_file=i386/sun.h
- use_collect2=yes
- ;;
- + pentium-*-bsd* | i[345]86-*-bsdi* | i[345]86-*-bsd386*)
- + cpu_type=i386
- + tm_file=i386/bsd386.h
- + # tmake_file=t-libc-ok
- + ;;
- i[345]86-*-aout*)
- cpu_type=i386
- tm_file=i386/i386-aout.h
- tmake_file=i386/t-i386bare
- ;;
- i[345]86-*-bsd*)
- cpu_type=i386
- tm_file=i386/386bsd.h
- ***************
- *** 931,960 ****
- # Next line turned off because both 386BSD and BSD/386 use GNU ld.
- # use_collect2=yes
- ;;
- ! i[345]86-*-freebsd*)
- cpu_type=i386
- tm_file=i386/freebsd.h
- - xm_file=i386/xm-freebsd.h
- # On FreeBSD, the headers are already ok.
- fixincludes=Makefile.in
- xmake_file=i386/x-freebsd
- ;;
- ! i[345]86-*-netbsd*)
- cpu_type=i386
- ! tm_file=i386/netbsd.h
- ! xm_file=i386/xm-netbsd.h
- # On NetBSD, the headers are already okay.
- fixincludes=Makefile.in
- - tmake_file=t-libc-ok
- xmake_file=x-netbsd
- ;;
- ! i[345]86-*-coff*)
- cpu_type=i386
- ! tm_file=i386/i386-coff.h
- ! tmake_file=i386/t-i386bare
- ! ;;
- ! i[345]86-*-gnu*)
- ! cpu_type=i386 # GNU supports this CPU; rest done below.
- ;;
- i[345]86-*-isc*) # 80386 running ISC system
- cpu_type=i386
- --- 930,959 ----
- # Next line turned off because both 386BSD and BSD/386 use GNU ld.
- # use_collect2=yes
- ;;
- ! pentium-*-freebsd* | i[345]86-*-freebsd*)
- cpu_type=i386
- tm_file=i386/freebsd.h
- # On FreeBSD, the headers are already ok.
- fixincludes=Makefile.in
- xmake_file=i386/x-freebsd
- ;;
- ! pentium-*-netbsd* | i[345]86-*-netbsd*)
- cpu_type=i386
- ! tm_file=i386/netbsd-i386.h
- # On NetBSD, the headers are already okay.
- fixincludes=Makefile.in
- xmake_file=x-netbsd
- ;;
- ! pentium-*-gnu* | i[345]86-*-gnu*)
- cpu_type=i386
- ! xm_file=i386/xm-gnu.h
- ! tm_file=i386/gnu.h
- ! tmake_file=t-libc-ok
- ! # GNU tools are the only tools.
- ! gnu_ld=yes
- ! gas=yes
- ! # On GNU, the headers are already okay.
- ! fixincludes=Makefile.in
- ;;
- i[345]86-*-isc*) # 80386 running ISC system
- cpu_type=i386
- ***************
- *** 972,1021 ****
- then
- tm_file=i386/iscdbx.h
- tmake_file=i386/t-svr3dbx
- - extra_parts="crtbegin.o crtend.o svr3.ifile svr3z.ifile"
- else
- tm_file=i386/isccoff.h
- - tmake_file=i386/t-crtstuff
- extra_parts="crtbegin.o crtend.o"
- fi
- install_headers_dir=install-headers-cpio
- broken_install=yes
- ;;
- ! i[345]86-*-linux*oldld*) # Intel 80386's running Linux
- ! cpu_type=i386 # with a.out format using pre BFD linkers
- ! xm_file=i386/xm-linux.h
- ! xmake_file=x-linux
- ! tm_file=i386/linux-oldld.h
- ! fixincludes=Makefile.in #On Linux, the headers are ok already.
- ! broken_install=yes
- ! gnu_ld=yes
- ! ;;
- ! i[345]86-*-linux*aout*) # Intel 80386's running Linux
- ! cpu_type=i386 # with a.out format
- xm_file=i386/xm-linux.h
- ! xmake_file=x-linux
- tm_file=i386/linux-aout.h
- fixincludes=Makefile.in #On Linux, the headers are ok already.
- broken_install=yes
- - gnu_ld=yes
- ;;
- ! i[345]86-*-linux*) # Intel 80386's running Linux
- ! cpu_type=i386 # with ELF format
- xm_file=i386/xm-linux.h
- ! xmake_file=x-linux
- tm_file=i386/linux.h
- fixincludes=Makefile.in #On Linux, the headers are ok already.
- broken_install=yes
- - gnu_ld=yes
- - # Don't use it. Linux uses a slightly different one.
- - # The real one comes with the Linux C library.
- - #extra_parts="crtbegin.o crtend.o"
- ;;
- ! i[345]86-go32-msdos | i[345]86-*-go32)
- ! cpu_type=i386
- ! tm_file=i386/go32.h
- ! ;;
- ! i[345]86-*-lynxos*)
- cpu_type=i386
- if [ x$gas = xyes ]
- then
- --- 971,1000 ----
- then
- tm_file=i386/iscdbx.h
- tmake_file=i386/t-svr3dbx
- else
- tm_file=i386/isccoff.h
- extra_parts="crtbegin.o crtend.o"
- fi
- install_headers_dir=install-headers-cpio
- broken_install=yes
- ;;
- ! pentium-*-linuxaout | i[345]86-*-linuxaout) # Intel 80386's running Linux
- ! cpu_type=i386
- xm_file=i386/xm-linux.h
- ! xmake_file=i386/x-linux
- tm_file=i386/linux-aout.h
- fixincludes=Makefile.in #On Linux, the headers are ok already.
- broken_install=yes
- ;;
- ! pentium-*-linux* | i[345]86-*-linux*) # Intel 80386's running Linux
- ! cpu_type=i386
- xm_file=i386/xm-linux.h
- ! xmake_file=i386/x-linux
- tm_file=i386/linux.h
- fixincludes=Makefile.in #On Linux, the headers are ok already.
- broken_install=yes
- ;;
- ! pentium-*-lynxos* | i[345]86-*-lynxos*)
- cpu_type=i386
- if [ x$gas = xyes ]
- then
- ***************
- *** 1027,1039 ****
- tmake_file=i386/t-i386bare
- xmake_file=x-lynx
- ;;
- ! i[345]86-*-mach*)
- cpu_type=i386
- tm_file=i386/mach.h
- # tmake_file=t-libc-ok
- use_collect2=yes
- ;;
- ! i[345]86-*-osfrose*) # 386 using OSF/rose
- cpu_type=i386
- if [ x$elf = xyes ]
- then
- --- 1006,1018 ----
- tmake_file=i386/t-i386bare
- xmake_file=x-lynx
- ;;
- ! pentium-*-mach* | i[345]86-*-mach*)
- cpu_type=i386
- tm_file=i386/mach.h
- # tmake_file=t-libc-ok
- use_collect2=yes
- ;;
- ! pentium-*-osfrose* | i[345]86-*-osfrose*) # 386 using OSF/rose
- cpu_type=i386
- if [ x$elf = xyes ]
- then
- ***************
- *** 1093,1099 ****
- fixincludes=fixinc.svr4
- broken_install=yes
- ;;
- ! i[345]86-*-sysv4*) # Intel 80386's running system V.4
- cpu_type=i386
- xm_file=i386/xm-sysv4.h
- if [ x$stabs = xyes ]
- --- 1072,1078 ----
- fixincludes=fixinc.svr4
- broken_install=yes
- ;;
- ! pentium-*-sysv4* | i[345]86-*-sysv4*) # Intel 80386's running system V.4
- cpu_type=i386
- xm_file=i386/xm-sysv4.h
- if [ x$stabs = xyes ]
- ***************
- *** 1106,1112 ****
- xmake_file=x-svr4
- extra_parts="crtbegin.o crtend.o"
- ;;
- ! i[345]86-*-sysv*) # Intel 80386's running system V
- cpu_type=i386
- xm_file=i386/xm-sysv3.h
- xmake_file=i386/x-sysv3
- --- 1085,1091 ----
- xmake_file=x-svr4
- extra_parts="crtbegin.o crtend.o"
- ;;
- ! pentium-*-sysv* | i[345]86-*-sysv*) # Intel 80386's running system V
- cpu_type=i386
- xm_file=i386/xm-sysv3.h
- xmake_file=i386/x-sysv3
- ***************
- *** 1116,1152 ****
- then
- tm_file=i386/svr3dbx.h
- tmake_file=i386/t-svr3dbx
- - extra_parts="svr3.ifile svr3z.rfile"
- else
- tm_file=i386/svr3gas.h
- extra_parts="crtbegin.o crtend.o"
- - tmake_file=i386/t-crtstuff
- fi
- else
- tm_file=i386/sysv3.h
- extra_parts="crtbegin.o crtend.o"
- - tmake_file=i386/t-crtstuff
- fi
- ;;
- ! i386-*-vsta) # Intel 80386's running VSTa kernel
- ! xm_file=i386/xm-vsta.h
- ! tm_file=i386/vsta.h
- ! tmake_file=i386/t-vsta
- ! xmake_file=i386/x-vsta
- ! ;;
- ! i[345]86-*-winnt3*)
- cpu_type=i386
- ! tm_file=i386/win-nt.h
- out_file=i386/i386.c
- xm_file=i386/xm-winnt.h
- ! xmake_file=winnt/x-winnt
- ! tmake_file=i386/t-winnt
- ! extra_objs="winnt.o oldnames.o"
- ! extra_gcc_objs="spawnv.o oldnames.o"
- ! fixincludes=fixinc.winnt
- if [ x$gnu_ld != xyes ]
- then
- ! extra_programs=ld.exe
- fi
- ;;
- i860-alliant-*) # Alliant FX/2800
- --- 1095,1118 ----
- then
- tm_file=i386/svr3dbx.h
- tmake_file=i386/t-svr3dbx
- else
- tm_file=i386/svr3gas.h
- extra_parts="crtbegin.o crtend.o"
- fi
- else
- tm_file=i386/sysv3.h
- extra_parts="crtbegin.o crtend.o"
- fi
- ;;
- ! pentium-*-winnt3* | i[345]86-*-winnt3*)
- cpu_type=i386
- ! tm_file=i386/winnt.h
- out_file=i386/i386.c
- xm_file=i386/xm-winnt.h
- ! xmake_file=i386/x-winnt
- if [ x$gnu_ld != xyes ]
- then
- ! extra_programs=ld
- fi
- ;;
- i860-alliant-*) # Alliant FX/2800
- ***************
- *** 2411,2420 ****
- esac
-
- # Distinguish i386 from i486/i586.
- ! # ??? For the moment we treat i586 as an i486.
- # Also, do not run mips-tfile on MIPS if using gas.
- case $machine in
- ! i[45]86-*-*)
- target_cpu_default=2
- ;;
- mips*-*-*)
- --- 2377,2392 ----
- esac
-
- # Distinguish i386 from i486/i586.
- ! # ??? For the moment we treat i586 as an i486. (NOT!)
- # Also, do not run mips-tfile on MIPS if using gas.
- case $machine in
- ! pentium-*-*)
- ! target_cpu_default=4
- ! ;;
- ! i586-*-*)
- ! target_cpu_default=4
- ! ;;
- ! i486-*-*)
- target_cpu_default=2
- ;;
- mips*-*-*)
- diff -rNci gcc-2.7.2/cse.c gcc-2.7.2p/cse.c
- *** gcc-2.7.2/cse.c Sun Nov 26 19:47:05 1995
- --- gcc-2.7.2p/cse.c Tue Jan 23 09:53:20 1996
- ***************
- *** 6136,6141 ****
- --- 6136,6164 ----
- sets = (struct set *) alloca (sizeof (struct set));
- sets[0].rtl = x;
-
- + /* intel1 */
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + if (IS_STACK_MODE (DFmode) && GET_CODE (SET_SRC (x)) == CONST_DOUBLE
- + && GET_CODE (SET_DEST (x)) == REG)
- + {
- + /* not worthwhile to hold on stack */
- + rtx tem = find_reg_note (insn, REG_EQUAL, 0);
- +
- + /* Record the actual constant value in a REG_EQUAL note, making
- + a new one if one does not already exist. */
- + if (tem)
- + XEXP (tem, 0) = SET_SRC(x);
- + else
- + REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
- + SET_SRC(x), REG_NOTES (insn));
- +
- + invalidate (SET_DEST (x), GET_MODE(x) );
- + }
- + else
- +
- + #endif
- + #endif
- /* Ignore SETs that are unconditional jumps.
- They never need cse processing, so this does not hurt.
- The reason is not efficiency but rather
- ***************
- *** 6762,6767 ****
- --- 6785,6816 ----
- if (dest == pc_rtx && src_const && GET_CODE (src_const) == LABEL_REF)
- src_folded = src_const, src_folded_cost = -1;
-
- + #ifdef SAVE_ON_REGS
- + /* intel1 If src is of form (reg1 OP const) and src_folded
- + is of form (reg2 OP const) and the costs are the same
- + and reg1 != reg2,
- + then bump up the cost of src_folded so that src will be
- + preferred. The reason for this is that if reg2 is used
- + here it's life may be extended thereby increasing register
- + pressure and causing superfulous movs. */
- + {
- + char * fmt;
- + if (src)
- + fmt = GET_RTX_FORMAT (GET_CODE (src));
- + if (src && src_folded && src_cost == src_folded_cost
- + && GET_CODE (src) == GET_CODE (src_folded)
- + && GET_RTX_LENGTH (GET_CODE (src)) == 2
- + && fmt[0] == 'e' && fmt[1] == 'e'
- + && GET_CODE (XEXP (src, 0)) == REG
- + && GET_CODE (XEXP (src, 1)) == CONST_INT
- + && GET_CODE (XEXP (src_folded, 0)) == REG
- + && GET_CODE (XEXP (src_folded, 1)) == CONST_INT
- + && !rtx_equal_p (XEXP (src, 0), XEXP (src_folded, 0)))
- + {
- + src_folded_cost++;
- + }
- + }
- + #endif
- /* Terminate loop when replacement made. This must terminate since
- the current contents will be tested and will always be valid. */
- while (1)
- ***************
- *** 7205,7210 ****
- --- 7254,7269 ----
- if (sets[i].src_elt == 0)
- {
- register struct table_elt *elt;
- + /* intel1 */
- + int do_rehash=0;
- +
- + /* intel1 */
- + if(GET_CODE(src)==REG &&
- + !REGNO_QTY_VALID_P (REGNO(src)))
- + { /* we will want to rehash all expressions based of src since
- + reg_qty[REGNO(src)] is about to change */
- + do_rehash = 1;
- + }
-
- /* Note that these insert_regs calls cannot remove
- any of the src_elt's, because they would have failed to
- diff -rNci gcc-2.7.2/expr.c gcc-2.7.2p/expr.c
- *** gcc-2.7.2/expr.c Sun Nov 26 16:18:07 1995
- --- gcc-2.7.2p/expr.c Tue Jan 23 09:53:21 1996
- ***************
- *** 24,29 ****
- --- 24,31 ----
- #include "rtl.h"
- #include "tree.h"
- #include "obstack.h"
- + /* intel1 */
- + #include "c-tree.h"
- #include "flags.h"
- #include "regs.h"
- #include "function.h"
- ***************
- *** 8954,8959 ****
- --- 8956,8967 ----
- && (i = floor_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))) >= 0
- && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
- && (type = type_for_mode (mode, 1)) != 0
- + /* intel1 */
- + && !(SLOW_SHORT_ACCESS
- + && (type == short_unsigned_type_node
- + || type == short_integer_type_node
- + || type == intHI_type_node
- + || type == unsigned_intHI_type_node))
- && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
- && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
- != CODE_FOR_nothing))
- ***************
- *** 9111,9116 ****
- --- 9119,9130 ----
- type = type_for_size (bitsize, unsignedp);
- if (! SLOW_BYTE_ACCESS
- && type != 0 && bitsize >= 0
- + /* intel1 */
- + && !(SLOW_SHORT_ACCESS
- + && (type == short_unsigned_type_node
- + || type == short_integer_type_node
- + || type == intHI_type_node
- + || type == unsigned_intHI_type_node))
- && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
- && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
- != CODE_FOR_nothing))
- diff -rNci gcc-2.7.2/flags.h gcc-2.7.2p/flags.h
- *** gcc-2.7.2/flags.h Thu Jun 15 11:34:11 1995
- --- gcc-2.7.2p/flags.h Tue Jan 23 09:25:25 1996
- ***************
- *** 361,363 ****
- --- 361,509 ----
- function. */
-
- extern int current_function_has_nonlocal_goto;
- +
- + /* intel1 our optimization controllers */
- +
- + /* Optimize usage of registers for memory addresses */
- +
- + extern int flag_opt_reg_use;
- +
- + /* Do reduce all the mem address givs */
- +
- + extern int flag_all_mem_givs;
- +
- + /* Try to treat index terms of addresses as reducible mem givs */
- +
- + extern int flag_reduce_index_givs;
- +
- + /* After reload try to replace spill slots with equivalent registers */
- +
- + extern int flag_peep_spills;
- +
- + /* After reload try to optimize usage of spill slots in loops */
- +
- + extern int flag_loop_after_global;
- +
- + /* In optimization of loops treats jumps backwards as not nullifying
- + optimization opportunities. */
- +
- + extern int flag_jump_back;
- +
- + /* Do loop copy propogation */
- +
- + extern int flag_copy_prop;
- +
- + /* Do compare elimination */
- +
- + extern int flag_compare_elim;
- +
- + /* Do a mini software pipelining on stack registers */
- +
- + extern int flag_sftwr_pipe;
- +
- + /* Try aggressive changing of jumps taken to jumps not taken */
- +
- + extern int flag_opt_jumps_out;
- +
- + /* Try to replace memory operands with equivalent registers in first
- + pass of loop optimize */
- +
- + extern int flag_replace_mem;
- +
- + /* Try to replace memory operands with equivalent stack registers in first
- + pass of loop optimize */
- +
- + extern int flag_replace_stack_mem;
- +
- + /* After reload if a register is marked dead at a copy into another
- + register - see if the other register can be used in the first place.
- + Thereby eleiminating the copy. */
- +
- + extern int flag_reg_reg_copy_opt;
- +
- + /* Move stack registers that will be compared for equality off, the
- + stack before the comparison. */
- +
- + extern int flag_do_offload;
- +
- + /* Optimize usage of stack registers from the stack */
- +
- + extern int flag_opt_reg_stack;
- +
- + /* cse is sometimes detrimental - see flow.c */
- +
- + extern int flag_correct_cse_mistakes;
- +
- + /* Try to push loads back into loops if the loaded register has been spilled */
- +
- + extern int flag_push_load_into_loop;
- +
- + /* After reload use available registers to load memory operands into
- + them and use the register instead of the memory operand. */
- +
- + extern int flag_risc;
- +
- + /* After reload use available registers to load CONST_INTs into
- + them and then store the register instead of the CONST_INT. */
- +
- + extern int flag_risc_const;
- +
- + /* Allow scheduler to try to swap two instructions when the
- + first increments a register by a constant and the second
- + uses that register as a base
- + */
- +
- + extern int flag_swap_for_agi;
- +
- + /* A destination that was riscified should stay that way. */
- +
- + extern int flag_risc_mem_dest;
- +
- + /* Try to use available registers so that a memory operand that is
- + reloaded will be reloaded into the same register. This helps
- + loop_after_global. */
- +
- + extern int flag_replace_reload_regs;
- +
- + /* If the riscified instruction has not changed it's place in
- + scheduling then recombine it into a cisc instruction. */
- +
- + extern int flag_recombine;
- +
- + /* These negative flags needed to override optimization
- + levels which turn them on by default */
- +
- + extern int flag_no_omit_frame_pointer;
- + extern int flag_no_risc;
- + extern int flag_no_risc_const;
- + extern int flag_no_risc_mem_dest;
- + extern int flag_no_recombine;
- + /* Use the first pass of the scheduler to rearrange between
- + insns that reference stack registers. */
- +
- + extern int flag_schedule_stack_reg_insns;
- +
- + /* Use the first pass of the scheduler to rearrange between
- + insns that reference stack registers and those that don't
- + but not amongst themselves */
- +
- + extern int flag_interleave_stack_non_stack;
- +
- + /* These negative flags needed to override optimization
- + levels which turn them on by default */
- +
- + extern int flag_no_schedule_stack_reg_insns;
- + extern int flag_no_interleave_stack_non_stack;
- +
- + extern int flag_sign_extension_elim;
- +
- + /* Try to lift memory disambiguated memory operands that are stored
- + to in a loop into a register for the duration of the loop. */
- +
- + extern int flag_lift_stores;
- +
- + /* As above but do the disambiguation at runtime. i.e. there
- + will be two copies of the loop, one disambiguated one not,
- + And the decision of which one to run will be made at runtime. */
- +
- + extern int flag_runtime_lift_stores;
- diff -rNci gcc-2.7.2/flow.c gcc-2.7.2p/flow.c
- *** gcc-2.7.2/flow.c Mon Aug 28 10:23:34 1995
- --- gcc-2.7.2p/flow.c Tue Jan 23 09:35:24 1996
- ***************
- *** 286,299 ****
- static HARD_REG_SET elim_reg_set;
-
- /* Forward declarations */
- ! static void find_basic_blocks PROTO((rtx, rtx));
- static int uses_reg_or_mem PROTO((rtx));
- static void mark_label_ref PROTO((rtx, rtx, int));
- ! static void life_analysis PROTO((rtx, int));
- void allocate_for_life_analysis PROTO((void));
- ! static void init_regset_vector PROTO((regset *, regset, int, int));
- static void propagate_block PROTO((regset, rtx, rtx, int,
- ! regset, int));
- static rtx flow_delete_insn PROTO((rtx));
- static int insn_dead_p PROTO((rtx, regset, int));
- static int libcall_dead_p PROTO((rtx, regset, rtx, rtx));
- --- 286,299 ----
- static HARD_REG_SET elim_reg_set;
-
- /* Forward declarations */
- ! static void find_basic_blocks PROTO((rtx, rtx, int));
- static int uses_reg_or_mem PROTO((rtx));
- static void mark_label_ref PROTO((rtx, rtx, int));
- ! static void life_analysis PROTO((rtx, int, int));
- void allocate_for_life_analysis PROTO((void));
- ! /* intel2 static */ void init_regset_vector PROTO((regset *, regset, int, int));
- static void propagate_block PROTO((regset, rtx, rtx, int,
- ! regset, int, int));
- static rtx flow_delete_insn PROTO((rtx));
- static int insn_dead_p PROTO((rtx, regset, int));
- static int libcall_dead_p PROTO((rtx, regset, rtx, rtx));
- ***************
- *** 307,322 ****
- --- 307,333 ----
- static int try_pre_increment PROTO((rtx, rtx, HOST_WIDE_INT));
- static rtx find_use_as_address PROTO((rtx, rtx, HOST_WIDE_INT));
- void dump_flow_info PROTO((FILE *));
- + /* intel1 */
- + static void correct_cse_mistakes ();
- + static void count_reg_uses ();
- + static void do_correction ();
-
- /* Find basic blocks of the current function and perform data flow analysis.
- F is the first insn of the function and NREGS the number of register numbers
- in use. */
-
- void
- + /*
- flow_analysis (f, nregs, file)
- + */
- + /* intel2 - added the change_f flag to disable changes to the insns, when called
- + * by memory_simplify. Don't apply any change to an insn if this flag == 0
- + */
- + flow_analysis (f, nregs, file, change_f)
- rtx f;
- int nregs;
- FILE *file;
- + int change_f; /* intel2 */
- {
- register rtx insn;
- register int i;
- ***************
- *** 326,331 ****
- --- 337,350 ----
- static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
- #endif
-
- + /* intel1 */
- + #ifdef SPARE_REGS
- + if (change_f && flag_opt_reg_stack)
- + {
- + nregs += SPARE_REGS;
- + }
- + #endif
- +
- /* Record which registers will be eliminated. We use this in
- mark_used_regs. */
-
- ***************
- *** 372,380 ****
- /* Allocate some tables that last till end of compiling this function
- and some needed only in find_basic_blocks and life_analysis. */
-
- ! n_basic_blocks = i;
- ! basic_block_head = (rtx *) oballoc (n_basic_blocks * sizeof (rtx));
- ! basic_block_end = (rtx *) oballoc (n_basic_blocks * sizeof (rtx));
- basic_block_drops_in = (char *) alloca (n_basic_blocks);
- basic_block_loop_depth = (short *) alloca (n_basic_blocks * sizeof (short));
- uid_block_number
- --- 391,403 ----
- /* Allocate some tables that last till end of compiling this function
- and some needed only in find_basic_blocks and life_analysis. */
-
- ! if (change_f || (n_basic_blocks!=i))
- ! /* intel2 if change_f is 0 we may have already allocated basic blocks */
- ! {
- ! n_basic_blocks = i;
- ! basic_block_head = (rtx *) oballoc (n_basic_blocks * sizeof (rtx));
- ! basic_block_end = (rtx *) oballoc (n_basic_blocks * sizeof (rtx));
- ! }
- basic_block_drops_in = (char *) alloca (n_basic_blocks);
- basic_block_loop_depth = (short *) alloca (n_basic_blocks * sizeof (short));
- uid_block_number
- ***************
- *** 382,392 ****
- uid_volatile = (char *) alloca (max_uid_for_flow + 1);
- bzero (uid_volatile, max_uid_for_flow + 1);
-
- ! find_basic_blocks (f, nonlocal_label_list);
- ! life_analysis (f, nregs);
- if (file)
- dump_flow_info (file);
-
- basic_block_drops_in = 0;
- uid_block_number = 0;
- basic_block_loop_depth = 0;
- --- 405,420 ----
- uid_volatile = (char *) alloca (max_uid_for_flow + 1);
- bzero (uid_volatile, max_uid_for_flow + 1);
-
- ! find_basic_blocks (f, nonlocal_label_list /* intel2: */, change_f);
- ! life_analysis (f, nregs /* intel2: */, change_f);
- if (file)
- dump_flow_info (file);
-
- + /* intel1 */
- + if (flag_correct_cse_mistakes && change_f)
- + {
- + correct_cse_mistakes (f, nregs, file);
- + }
- basic_block_drops_in = 0;
- uid_block_number = 0;
- basic_block_loop_depth = 0;
- ***************
- *** 400,407 ****
- NONLOCAL_LABEL_LIST is the same local variable from flow_analysis. */
-
- static void
- ! find_basic_blocks (f, nonlocal_label_list)
- rtx f, nonlocal_label_list;
- {
- register rtx insn;
- register int i;
- --- 428,436 ----
- NONLOCAL_LABEL_LIST is the same local variable from flow_analysis. */
-
- static void
- ! find_basic_blocks (f, nonlocal_label_list /* intel2: */, change_f)
- rtx f, nonlocal_label_list;
- + int change_f;/* intel2 */
- {
- register rtx insn;
- register int i;
- ***************
- *** 634,642 ****
- They can occur because jump_optimize does not recognize
- unreachable loops as unreachable. */
-
- ! deleted = 0;
- for (i = 0; i < n_basic_blocks; i++)
- ! if (!block_live[i])
- {
- deleted++;
-
- --- 663,671 ----
- They can occur because jump_optimize does not recognize
- unreachable loops as unreachable. */
-
- ! deleted=0;
- for (i = 0; i < n_basic_blocks; i++)
- ! if (!block_live[i] /* intel2: */ && change_f)
- {
- deleted++;
-
- ***************
- *** 874,882 ****
- regset_size and regset_bytes are also set here. */
-
- static void
- ! life_analysis (f, nregs)
- rtx f;
- int nregs;
- {
- register regset tem;
- int first_pass;
- --- 903,912 ----
- regset_size and regset_bytes are also set here. */
-
- static void
- ! life_analysis (f, nregs /* intel2: */, change_f)
- rtx f;
- int nregs;
- + int change_f; /* intel2 */
- {
- register regset tem;
- int first_pass;
- ***************
- *** 904,911 ****
-
- max_regno = nregs;
-
- - bzero (regs_ever_live, sizeof regs_ever_live);
-
- /* Allocate and zero out many data structures
- that will record the data from lifetime analysis. */
-
- --- 934,947 ----
-
- max_regno = nregs;
-
-
- + /* intel2 - begin */
- + /* Dont reset the regs_ever_live array if called from memory_simplify */
- + if (change_f)
- + {
- + /* intel2 - end */
- + bzero (regs_ever_live, sizeof regs_ever_live);
- + }
- /* Allocate and zero out many data structures
- that will record the data from lifetime analysis. */
-
- ***************
- *** 950,959 ****
- for (insn = f; insn; insn = NEXT_INSN (insn))
- {
- enum rtx_code code1 = GET_CODE (insn);
- ! if (code1 == CALL_INSN)
- INSN_VOLATILE (insn) = 1;
- else if (code1 == INSN || code1 == JUMP_INSN)
- {
- /* Delete (in effect) any obvious no-op moves. */
- if (GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- --- 986,1017 ----
- for (insn = f; insn; insn = NEXT_INSN (insn))
- {
- enum rtx_code code1 = GET_CODE (insn);
- ! if (code1 == CALL_INSN /* intel2: */ && change_f)
- INSN_VOLATILE (insn) = 1;
- else if (code1 == INSN || code1 == JUMP_INSN)
- {
- + /* intel2 - begin */
- + /* if change_f is reset, i.e. we are called from memory_simplify, and
- + * therefore we would like to update the insn's REG_DEAD notes.
- + * If we find a REG_DEAD note, we remove it here.
- + */
- + if (!change_f)
- + {
- + register rtx note;
- +
- +
- + for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- + if (REG_NOTE_KIND (note) == REG_DEAD
- + || REG_NOTE_KIND (note) == REG_UNUSED)
- + remove_note(insn, note);
- + }
- + /* intel2 - end */
- +
- +
- + /* intel2 - begin */
- + if (change_f)
- + {
- + /* intel2 - end */
- /* Delete (in effect) any obvious no-op moves. */
- if (GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- ***************
- *** 1014,1019 ****
- --- 1072,1080 ----
- #endif
- && XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx)
- INSN_VOLATILE (insn) = 1;
- + /* intel2 - begin */
- + } /* if (change_f) */
- + /* intel2 - end */
- }
- }
-
- ***************
- *** 1154,1160 ****
- basic_block_head[i], basic_block_end[i], 0,
- first_pass ? basic_block_significant[i]
- : (regset) 0,
- ! i);
- }
-
- {
- --- 1215,1221 ----
- basic_block_head[i], basic_block_end[i], 0,
- first_pass ? basic_block_significant[i]
- : (regset) 0,
- ! i/* intel2: */, change_f);
- }
-
- {
- ***************
- *** 1219,1225 ****
- {
- propagate_block (basic_block_live_at_end[i],
- basic_block_head[i], basic_block_end[i], 1,
- ! (regset) 0, i);
- #ifdef USE_C_ALLOCA
- alloca (0);
- #endif
- --- 1280,1286 ----
- {
- propagate_block (basic_block_live_at_end[i],
- basic_block_head[i], basic_block_end[i], 1,
- ! (regset) 0, i/* intel2: */, change_f);
- #ifdef USE_C_ALLOCA
- alloca (0);
- #endif
- ***************
- *** 1316,1322 ****
- SPACE is of type regset, but it is really as long as NELTS regsets.
- BYTES_PER_ELT is the number of bytes in one regset. */
-
- ! static void
- init_regset_vector (vector, space, nelts, bytes_per_elt)
- regset *vector;
- regset space;
- --- 1377,1383 ----
- SPACE is of type regset, but it is really as long as NELTS regsets.
- BYTES_PER_ELT is the number of bytes in one regset. */
-
- ! /* intel2 static */ void
- init_regset_vector (vector, space, nelts, bytes_per_elt)
- regset *vector;
- regset space;
- ***************
- *** 1353,1365 ****
- BNUM is the number of the basic block. */
-
- static void
- ! propagate_block (old, first, last, final, significant, bnum)
- register regset old;
- rtx first;
- rtx last;
- int final;
- regset significant;
- ! int bnum;
- {
- register rtx insn;
- rtx prev;
- --- 1414,1426 ----
- BNUM is the number of the basic block. */
-
- static void
- ! propagate_block (old, first, last, final, significant, bnum /* intel2: */, change_f)
- register regset old;
- rtx first;
- rtx last;
- int final;
- regset significant;
- ! int bnum /* intel2: */, change_f;
- {
- register rtx insn;
- rtx prev;
- ***************
- *** 1403,1409 ****
- loop_depth--;
- }
-
- ! if (final)
- {
- register int i, offset;
- REGSET_ELT_TYPE bit;
- --- 1464,1470 ----
- loop_depth--;
- }
-
- ! if (final /* intel2: */ && change_f)
- {
- register int i, offset;
- REGSET_ELT_TYPE bit;
- ***************
- *** 1487,1493 ****
- "delete" it by turning it into a NOTE of type NOTE_INSN_DELETED.
- We could really delete it with delete_insn, but that
- can cause trouble for first or last insn in a basic block. */
- ! if (final && insn_is_dead)
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- --- 1548,1554 ----
- "delete" it by turning it into a NOTE of type NOTE_INSN_DELETED.
- We could really delete it with delete_insn, but that
- can cause trouble for first or last insn in a basic block. */
- ! if (final /* intel2: */ && change_f && insn_is_dead)
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- ***************
- *** 1529,1535 ****
- {
- register rtx x = PATTERN (insn);
- /* Does this instruction increment or decrement a register? */
- ! if (final && GET_CODE (x) == SET
- && GET_CODE (SET_DEST (x)) == REG
- && (GET_CODE (SET_SRC (x)) == PLUS
- || GET_CODE (SET_SRC (x)) == MINUS)
- --- 1590,1596 ----
- {
- register rtx x = PATTERN (insn);
- /* Does this instruction increment or decrement a register? */
- ! if (final /* intel2: */ && change_f && GET_CODE (x) == SET
- && GET_CODE (SET_DEST (x)) == REG
- && (GET_CODE (SET_SRC (x)) == PLUS
- || GET_CODE (SET_SRC (x)) == MINUS)
- ***************
- *** 1573,1579 ****
- live. */
-
- mark_set_regs (old, dead, PATTERN (insn),
- ! final ? insn : NULL_RTX, significant);
-
- /* If an insn doesn't use CC0, it becomes dead since we
- assume that every insn clobbers it. So show it dead here;
- --- 1634,1640 ----
- live. */
-
- mark_set_regs (old, dead, PATTERN (insn),
- ! (final /* intel2: */ && change_f) ? insn : NULL_RTX, significant);
-
- /* If an insn doesn't use CC0, it becomes dead since we
- assume that every insn clobbers it. So show it dead here;
- ***************
- *** 1637,1643 ****
- old[i] |= live[i];
- }
-
- ! if (GET_CODE (insn) == CALL_INSN && final)
- {
- /* Any regs live at the time of a call instruction
- must not go in a register clobbered by calls.
- --- 1698,1704 ----
- old[i] |= live[i];
- }
-
- ! if (GET_CODE (insn) == CALL_INSN && final /* intel2: */ && change_f)
- {
- /* Any regs live at the time of a call instruction
- must not go in a register clobbered by calls.
- ***************
- *** 1655,1661 ****
- into MAXLIVE and REGS_SOMETIMES_LIVE.
- Also update counts of how many insns each reg is live at. */
-
- ! if (final)
- {
- for (i = 0; i < regset_size; i++)
- {
- --- 1716,1722 ----
- into MAXLIVE and REGS_SOMETIMES_LIVE.
- Also update counts of how many insns each reg is live at. */
-
- ! if (final /* intel2: */ && change_f)
- {
- for (i = 0; i < regset_size; i++)
- {
- ***************
- *** 2878,2883 ****
- --- 2939,2949 ----
- {
- register int i;
- static char *reg_class_names[] = REG_CLASS_NAMES;
- + /* intel1 */
- + #ifdef SPARE_REGS
- + int max_regno;
- + max_regno = max_reg_num();
- + #endif
-
- fprintf (file, "%d registers.\n", max_regno);
-
- ***************
- *** 2954,2956 ****
- --- 3020,3613 ----
- }
- fprintf (file, "\n");
- }
- +
- + /* intel1 */
- + /* Information about registers */
- + struct regopt_info
- + {
- + rtx insn_set; /* If non NULL then the insn that loads the register
- + with it's current value */
- + int num_uses_copied; /* To count if the reg setter has been copied to
- + each of the uses */
- + char copied_for_src; /* Set per insn if the insn_set has been copied
- + as a result of analysis on the src */
- + };
- + static struct regopt_info *rinfo;
- +
- + /* Count the number of new sets of the register */
- + static int *my_reg_n_sets;
- +
- + /* Count the number of times a register is used in an insn */
- + static int *regs_in_body;
- +
- + /* Count the number of times a register is used in a function */
- + static int *reg_n_uses;
- +
- + /* Copied from sched.c
- + Return the INSN_LIST containing INSN in LIST, or NULL
- + if LIST does not contain INSN. */
- + #ifndef __GNUC__
- + #define __inline
- + #endif
- +
- + __inline static rtx
- + find_insn_list (insn, list)
- + rtx insn;
- + rtx list;
- + {
- + while (list)
- + {
- + if (XEXP (list, 0) == insn)
- + return list;
- + list = XEXP (list, 1);
- + }
- + return 0;
- + }
- +
- + /*
- + Sometimes cse is done where it is detremental. Consider register 23
- + in the following insn stream:
- +
- + (insn 18 65 82 (set (reg/v:SI 23)
- + (plus:SI (reg/v:SI 22)
- + (const_int -4501))) 32 {movsi+1} (nil)
- + (nil))
- +
- + (insn 82 18 83 (set (cc0)
- + (compare:CC (reg/v:SI 22)
- + (const_int 4500))) 6 {cmpsi_cc} (nil)
- + (nil))
- +
- + (jump_insn 83 82 90 (set (pc)
- + (if_then_else (gt (cc0)
- + (const_int 0))
- + (label_ref 63)
- + (pc))) 185 {bgt+1} (nil)
- + (nil))
- +
- + (note 90 83 91 "" NOTE_INSN_DELETED)
- +
- + (insn 91 90 93 (set (reg:SI 32)
- + (ashift:SI (reg/v:SI 23)
- + (const_int 2))) 136 {ashlsi3} (nil)
- + (expr_list:REG_DEAD (reg/v:SI 23)
- + (nil)))
- +
- + reg 23 appears in insn 91 as a result of cse, before cse insn 90
- + and 91 were:
- +
- + (insn 90 83 91 (set (reg:SI 33)
- + (plus:SI (reg/v:SI 22)
- + (const_int -4501))) -1 (nil)
- + (nil))
- +
- + (insn 91 90 93 (set (reg:SI 34)
- + (ashift:SI (reg:SI 33)
- + (const_int 2))) -1 (nil)
- + (nil))
- +
- + since reg 23 does not appear anywhere else in the rtl and it is dead
- + at insn 91 it would be better to move insn 18 to after insn 90, thus
- + allowing the combiner to combine insn 18 into 91.
- +
- + */
- + static void
- + correct_cse_mistakes (f, cur_max_reg, dump_file)
- + rtx f;
- + int cur_max_reg;
- + FILE *dump_file;
- + {
- + rtx insn, src, dest, insn_set, note;
- + struct regs_mentioned *header, *a_reg_used;
- + int num_regs, recog_ok, i, regno;
- + char *storage1, *storage2;
- +
- + rinfo =
- + (struct regopt_info *) alloca ((cur_max_reg) * sizeof (struct regopt_info));
- + bzero (rinfo, (cur_max_reg) * sizeof (struct regopt_info));
- + reg_n_uses = (int *) alloca ((cur_max_reg) * sizeof (int));
- + bzero (reg_n_uses, (cur_max_reg) * sizeof (int));
- + regs_in_body = (int *) alloca ((cur_max_reg) * sizeof (int));
- + bzero (regs_in_body, (cur_max_reg) * sizeof (int));
- + my_reg_n_sets = (int *) alloca ((cur_max_reg) * sizeof (int));
- + bzero (my_reg_n_sets, (cur_max_reg) * sizeof (int));
- +
- + if (dump_file)
- + fprintf (dump_file, "\ndoing correct_cse_mistakes:\n\n");
- + insn = f;
- + while (insn)
- + {
- + if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
- + || GET_CODE (insn) == CALL_INSN)
- + {
- + count_reg_uses (PATTERN (insn), reg_n_uses);
- + }
- + insn = NEXT_INSN (insn);
- + }
- + insn = f;
- + while (insn)
- + {
- + switch (GET_CODE (insn))
- + {
- +
- + case CALL_INSN:
- + /* Don't want to change reg_n_calls_crosses */
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + break;
- +
- + case CODE_LABEL:
- + case BARRIER:
- + /* forget everything */
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + break;
- +
- + case INSN:
- + if (GET_CODE (PATTERN (insn)) == CLOBBER)
- + {
- + if (GET_CODE (SET_DEST (PATTERN (insn))) == REG)
- + {
- + rinfo[ REGNO (SET_DEST (PATTERN (insn)))].insn_set = NULL;
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && reg_overlap_mentioned_p (SET_DEST (PATTERN (insn)),
- + SET_SRC (PATTERN (rinfo[i].insn_set)))
- + )
- + { /* current value of reg dest overwritten */
- + rinfo[i].insn_set = NULL;
- + }
- + }
- + }
- + }
- + else if (GET_CODE (PATTERN (insn)) == PARALLEL)
- + {
- + for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- + {
- + rtx cur_rtx;
- + cur_rtx = XVECEXP (PATTERN (insn), 0, i);
- + if ((GET_CODE (cur_rtx) == SET
- + || GET_CODE (cur_rtx) == CLOBBER)
- + && GET_CODE (SET_DEST (cur_rtx)) == REG)
- + {
- + rinfo[ REGNO (SET_DEST (cur_rtx))].insn_set = NULL;
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && reg_overlap_mentioned_p (SET_DEST (cur_rtx),
- + SET_SRC (PATTERN (rinfo[i].insn_set)))
- + )
- + { /* current value of reg dest overwritten */
- + rinfo[i].insn_set = NULL;
- + }
- + }
- + }
- + if (!(GET_CODE (cur_rtx) == SET
- + || GET_CODE (cur_rtx) == CLOBBER
- + || GET_CODE (cur_rtx) == USE))
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + }
- + else if (GET_CODE (PATTERN (insn)) == SET)
- + {
- + dest = SET_DEST (PATTERN (insn));
- + src = SET_SRC (PATTERN (insn));
- + if (GET_CODE (src) == REG)
- + {
- + i = REGNO (src);
- + if (rinfo[i].insn_set
- + && BLOCK_NUM (insn) == BLOCK_NUM (rinfo[i].insn_set))
- + { /* Since insn_set cannot be deleted stop optimization */
- + rinfo[i].insn_set = NULL;
- + }
- + }
- + else /* (GET_CODE (src) != REG) */
- + {
- + count_reg_uses (src, regs_in_body);
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && regs_in_body[i]
- + && BLOCK_NUM (insn) == BLOCK_NUM (rinfo[i].insn_set))
- + { /* Since insn_set cannot be deleted stop optimization */
- + rinfo[i].insn_set = NULL;
- + }
- + if (reg_n_sets[i] == 1
- + && regs_in_body[i]
- + && rinfo[i].insn_set
- + && GET_CODE (rinfo[i].insn_set) == INSN)
- + {
- + if (find_regno_note (insn, REG_DEAD, i))
- + {
- + /* copy insn_set just prior to insn */
- + do_correction (i, insn, dump_file);
- + }
- + else
- + { /* A use that is not dead - stop. */
- + rinfo[i].insn_set = NULL;
- + }
- + }
- + }
- + bzero (regs_in_body, cur_max_reg * sizeof (int));
- + }
- + if (GET_CODE (dest) != REG)
- + {
- + count_reg_uses (dest, regs_in_body);
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && regs_in_body[i]
- + && BLOCK_NUM (insn) == BLOCK_NUM (rinfo[i].insn_set))
- + { /* Since insn_set cannot be deleted stop optimization */
- + rinfo[i].insn_set = NULL;
- + }
- + if (reg_n_sets[i] == 1
- + && !rinfo[i].copied_for_src
- + && regs_in_body[i]
- + && rinfo[i].insn_set
- + && GET_CODE (rinfo[i].insn_set) == INSN)
- + {
- + if (find_regno_note (insn, REG_DEAD, i))
- + {
- + /* copy insn_set just prior to insn */
- + do_correction (i, insn, dump_file);
- + }
- + else
- + { /* A use that is not dead - stop. */
- + rinfo[i].insn_set = NULL;
- + }
- +
- + }
- + }
- + bzero (regs_in_body, cur_max_reg * sizeof (int));
- + }
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + rinfo[i].copied_for_src = 0;
- + }
- + if (GET_CODE (dest) == REG)
- + {
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && reg_overlap_mentioned_p (dest, SET_SRC (PATTERN (rinfo[i].insn_set)))
- + )
- + { /* current value of reg dest overwritten */
- + rinfo[i].insn_set = NULL;
- + }
- + }
- + if (reg_overlap_mentioned_p (dest, SET_SRC (PATTERN (insn))))
- + {
- + rinfo[REGNO (dest)].insn_set = NULL;
- + }
- + else
- + {
- + if ((GET_CODE (SET_SRC (PATTERN (insn))) == ASHIFT
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
- + || (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == SYMBOL_REF)
- + || (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == MULT
- + && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0)) == REG
- + && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 1)) == CONST_INT
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
- + || (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
- + )
- + { /* these may be combinable */
- + if (REG_NOTES (insn) == NULL)
- + { /* Don't want to mess around with
- + the REG_NOTES. */
- + rinfo[REGNO (dest)].insn_set = insn;
- + }
- + }
- + else
- + {
- + rinfo[REGNO (dest)].insn_set = NULL;
- + }
- + }
- + }
- + }
- + else if (GET_CODE (PATTERN (insn)) == USE)
- + ; /* nothing */
- + else
- + {
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + /* A register that dies cannot be used further in a substitution. */
- + for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- + if (REG_NOTE_KIND (note) == REG_DEAD
- + && GET_CODE (XEXP (note, 0)) == REG)
- + {
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && reg_overlap_mentioned_p (XEXP (note, 0),
- + SET_SRC (PATTERN (rinfo[i].insn_set)))
- + )
- + {
- + rinfo[i].insn_set = NULL;
- + }
- + }
- + }
- +
- + break;
- +
- + case JUMP_INSN:
- + case NOTE:
- + break;
- +
- + default:
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + break;
- + }
- + insn = NEXT_INSN (insn);
- + }
- + for (i = 0; i < cur_max_reg; i++)
- + reg_n_sets[i] += my_reg_n_sets[i];
- + }
- +
- + /*
- + Increment the reg_n_uses element for each register mentioned in body
- + and for each time it is mentioned
- + */
- + static void
- + count_reg_uses (body, where_to_count)
- + rtx body;
- + int *where_to_count;
- + {
- + int i, j, ret_val = 0;
- + char *fmt;
- + register RTX_CODE code = GET_CODE (body);
- +
- + if (code == CLOBBER)
- + return;
- + else if (code == REG)
- + where_to_count[REGNO (body)]++;
- + else if (code == SET)
- + {
- + if (GET_CODE (SET_DEST (body)) != REG)
- + {
- + count_reg_uses (SET_DEST (body), where_to_count);
- + }
- + count_reg_uses (SET_SRC (body), where_to_count);
- + }
- + else
- + {
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + count_reg_uses (XEXP (body, i), where_to_count);
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (body, i); j++)
- + count_reg_uses (XVECEXP (body, i, j), where_to_count);
- + }
- + }
- + }
- +
- + /*
- + Copy the insn that sets regnum to just before insn.
- + If that insn has been copied to in front of each of
- + it's uses then delete it
- + */
- + static void
- + do_correction (regnum, insn, dump_file)
- + int regnum;
- + rtx insn;
- + FILE * dump_file;
- + {
- + rtx insn_set;
- + int i;
- +
- + insn_set
- + = rinfo[regnum].insn_set;
- + if (BLOCK_NUM (insn) == BLOCK_NUM (insn_set))
- + { /* Since insn_set cannot be deleted stop optimization */
- + rinfo[regnum].insn_set = NULL;
- + return;
- + }
- + emit_insn_before (
- + copy_rtx (PATTERN (insn_set)),
- + insn);
- +
- + if (REG_NOTES (insn_set))
- + {
- + REG_NOTES (PREV_INSN (insn))
- + = copy_rtx (REG_NOTES (insn_set));
- + }
- + LOG_LINKS (insn)
- + = gen_rtx (INSN_LIST, VOIDmode, PREV_INSN (insn),
- + LOG_LINKS (insn));
- + if (find_insn_list (insn_set,
- + LOG_LINKS (insn)))
- + remove_dependence (insn, insn_set);
- + rinfo[regnum].num_uses_copied += regs_in_body[regnum];
- + my_reg_n_sets[regnum]++;
- + if (dump_file)
- + {
- + fprintf (dump_file,
- + " copy insn %d to before insn %d\n",
- + INSN_UID (insn_set), INSN_UID (insn));
- + }
- + if (rinfo[regnum].num_uses_copied == reg_n_uses[regnum])
- + { /* insn_set is no longer relevant - delete it */
- + rinfo[regnum].insn_set = NULL;
- + PUT_CODE (insn_set, NOTE);
- + NOTE_LINE_NUMBER (insn_set) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (insn_set) = 0;
- + if (dump_file)
- + {
- + fprintf (dump_file,
- + " delete insn %d \n",
- + INSN_UID (insn_set));
- + }
- + reg_n_sets[regnum]--;
- + }
- + /* If insn was a basic block head then now the copy is
- + the basic block head. */
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + if (basic_block_head[i] == insn)
- + {
- + basic_block_head[i] = PREV_INSN (insn);
- + break;
- + }
- + }
- +
- + }
- +
- + /* intel2 */
- + /* Call flow_analysis without changing insns, and if save_pseudo is set, saves
- + the basic_block_live_at_start information, concerning the pseudo registers,
- + and restores it after flow_analysis. */
- +
- + void
- + hard_reg_flow_analysis (f, file, save_pseudo)
- + rtx f;
- + FILE *file;
- + int save_pseudo;
- + {
- + int limit;
- + register int block, regno;
- +
- + /* Element N is a regset describing the registers live
- + at the start of basic block N, as was saved before the call to
- + flow_analysis. We use it to restore the contents of the pseudo registers,
- + needed by other phases. */
- +
- + regset *basic_block_live_at_start_saved;
- +
- + #if 0
- + register int j;
- + #endif
- +
- + if (save_pseudo)
- + {
- + int regset_size = ((max_regno + REGSET_ELT_BITS - 1) / REGSET_ELT_BITS);
- + int regset_bytes = regset_size * sizeof (*(regset)0);
- + basic_block_live_at_start_saved =
- + (regset *) alloca (n_basic_blocks * sizeof (regset));
- + /* copy basic_block_live_at_start to basic_block_live_at_start_saved */
- + for (block = 0; block < n_basic_blocks; block++)
- + {
- + basic_block_live_at_start_saved[block] = (regset) alloca (regset_bytes);
- + bcopy (basic_block_live_at_start[block],
- + basic_block_live_at_start_saved[block],
- + regset_bytes);
- + }
- +
- + #if 0
- + /* Check if copy is o.k. */
- + if (file)
- + {
- + fprintf (file, "Pseudo registers live at start:\n");
- +
- + for (block = 0; block < n_basic_blocks; block++)
- + {
- + fprintf (file, "\nBlock no. %d original:", block);
- +
- + for (regno = FIRST_PSEUDO_REGISTER; regno < max_regno; regno++)
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register REGSET_ELT_TYPE bit
- + = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- + if ((basic_block_live_at_start_saved[block][offset] & bit)
- + ^ (basic_block_live_at_start[block][offset] & bit))
- + {
- + fprintf (file, "\nERROR: differnt values in regsets!\n");
- + fprintf (file,
- + "original: %d, saved: %d\n",
- + basic_block_live_at_start[block][offset],
- + basic_block_live_at_start_saved[block][offset]);
- + abort ();
- + }
- + if (basic_block_live_at_start[block][offset] & bit)
- + fprintf (file, " %d", regno);
- + }
- + fprintf (file, "\nSaved:");
- + for (regno = FIRST_PSEUDO_REGISTER; regno < max_regno; regno++)
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register REGSET_ELT_TYPE bit
- + = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- +
- + if (basic_block_live_at_start_saved[block][offset] & bit)
- + fprintf (file, " %d", regno);
- + }
- + fprintf (file, "\n");
- + } /* for (block = 0; block < n_basic_blocks; block++) */
- + } /* if (file) */
- + #endif
- + } /* if (save_pseudo) */
- +
- + limit = max_reg_num ();
- +
- + /* Do control and data flow analysis, and write the results to the dump
- + * file, if dump wanted.
- + */
- + flow_analysis (f, limit, file, 0 /* do not allow a change to the insns */ );
- +
- + if (save_pseudo)
- + {
- + /* restore the contents of pseudo registers if basic_block_live_at_start */
- + for (block = 0; block < n_basic_blocks; block++)
- + {
- + for (regno = FIRST_PSEUDO_REGISTER; regno < max_regno; regno++)
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register REGSET_ELT_TYPE bit
- + = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- +
- + if (basic_block_live_at_start_saved[block][offset] & bit)
- + basic_block_live_at_start[block][offset] |= bit;
- + else
- + basic_block_live_at_start[block][offset] &= ~bit;
- + }
- + }
- +
- + #if 0
- + /* Check if copy is o.k. */
- + if (file)
- + {
- + fprintf (file, "Pseudo registers live at start - restored :\n");
- +
- + for (block = 0; block < n_basic_blocks; block++)
- + {
- + fprintf (file, "Block no. %d:", block);
- + for (regno = FIRST_PSEUDO_REGISTER; regno < max_regno; regno++)
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register REGSET_ELT_TYPE bit
- + = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- + if (basic_block_live_at_start[block][offset] & bit)
- + fprintf (file, " %d", regno);
- + }
- + fprintf (file, "\n");
- + }
- + }
- + #endif
- + } /* if (save_pseudo) */
- + } /* hard_reg_flow_analysis (f, file, save_pseudo) */
- diff -rNci gcc-2.7.2/fold-const.c gcc-2.7.2p/fold-const.c
- *** gcc-2.7.2/fold-const.c Fri Sep 15 22:26:12 1995
- --- gcc-2.7.2p/fold-const.c Tue Jan 23 09:35:24 1996
- ***************
- *** 3645,3651 ****
- return fold (build (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
- else if (! FLOAT_TYPE_P (type))
- {
- ! if (integer_zerop (arg1))
- return non_lvalue (convert (type, arg0));
-
- /* If we are adding two BIT_AND_EXPR's, both of which are and'ing
- --- 3645,3656 ----
- return fold (build (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
- else if (! FLOAT_TYPE_P (type))
- {
- ! if (integer_zerop (arg1)
- ! /* intel1 if it is pointer_type then removing the + 0 here
- ! will cause references to array[0] not to be marked
- ! as MEM_IN_STRUCT_P. So just leave the + 0 here - it
- ! will be removed when the tree is made into rtl anyway. */
- ! && TREE_CODE (TREE_TYPE (arg0)) != POINTER_TYPE)
- return non_lvalue (convert (type, arg0));
-
- /* If we are adding two BIT_AND_EXPR's, both of which are and'ing
- ***************
- *** 4010,4015 ****
- --- 4015,4045 ----
- case FLOOR_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case EXACT_DIV_EXPR:
- + /* intel1 - implemet x/C where c is floating point and a power of two
- + as x*(1/C)
- + */
- + #ifndef REAL_IS_NOT_DOUBLE
- + if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
- + && TREE_CODE (t) == RDIV_EXPR
- + && TREE_CODE (TREE_TYPE (t)) == REAL_TYPE
- + && TYPE_NAME (TREE_TYPE (t))
- + && TREE_CODE (TYPE_NAME TREE_TYPE (t)) == TYPE_DECL
- + && TREE_CODE (TREE_OPERAND (t, 1)) == REAL_CST
- + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 1))) == REAL_TYPE
- + && TYPE_NAME (TREE_TYPE (TREE_OPERAND (t, 1)))
- + && TREE_CODE (TYPE_NAME (TREE_TYPE (TREE_OPERAND(t, 1))))== TYPE_DE CL
- + && TREE_REAL_CST (TREE_OPERAND (t, 1)) >= 2.0
- + && TREE_REAL_CST (TREE_OPERAND (t, 1))
- + ==(double)(REAL_VALUE_UNSIGNED_FIX(TREE_REAL_CST(TREE_OPERAND(t, 1))))
- + &&exact_log2(REAL_VALUE_UNSIGNED_FIX(TREE_REAL_CST(TREE_OPERAND(t,1)))) != -1
- + )
- + {
- + TREE_SET_CODE (t, MULT_EXPR);
- + code = TREE_CODE (t);
- + TREE_REAL_CST (TREE_OPERAND (t, 1))
- + = 1.0 / TREE_REAL_CST (TREE_OPERAND (t, 1));
- + }
- + #endif
- if (integer_onep (arg1))
- return non_lvalue (convert (type, arg0));
- if (integer_zerop (arg1))
- diff -rNci gcc-2.7.2/jump.c gcc-2.7.2p/jump.c
- *** gcc-2.7.2/jump.c Thu Oct 26 11:27:39 1995
- --- gcc-2.7.2p/jump.c Tue Jan 23 09:35:27 1996
- ***************
- *** 1920,1926 ****
-
- /* First, cross jumping of conditional jumps: */
-
- ! if (cross_jump && condjump_p (insn))
- {
- rtx newjpos, newlpos;
- rtx x = prev_real_insn (JUMP_LABEL (insn));
- --- 1920,1935 ----
-
- /* First, cross jumping of conditional jumps: */
-
- ! if (cross_jump && condjump_p (insn)
- ! /* intel1 */
- ! #ifdef NO_CROSS_JUMP_ON_LOOP_ENTRY
- ! && !(GET_CODE (NEXT_INSN(insn)) == NOTE
- ! &&
- ! (NOTE_LINE_NUMBER (NEXT_INSN(insn)) == NOTE_INSN_LOOP_BEG
- ! || NOTE_LINE_NUMBER (NEXT_INSN(insn)) == NOTE_INSN_LOOP_END)
- ! )
- ! #endif
- ! )
- {
- rtx newjpos, newlpos;
- rtx x = prev_real_insn (JUMP_LABEL (insn));
- diff -rNci gcc-2.7.2/loop.c gcc-2.7.2p/loop.c
- *** gcc-2.7.2/loop.c Tue Oct 3 16:17:16 1995
- --- gcc-2.7.2p/loop.c Tue Jan 23 09:25:29 1996
- ***************
- *** 39,44 ****
- --- 39,45 ----
- #include "rtl.h"
- #include "obstack.h"
- #include "expr.h"
- + #include "basic-block.h" /* intel1 */
- #include "insn-config.h"
- #include "insn-flags.h"
- #include "regs.h"
- ***************
- *** 46,51 ****
- --- 47,53 ----
- #include "recog.h"
- #include "flags.h"
- #include "real.h"
- + #include "reload.h" /* intel1 */
- #include "loop.h"
-
- /* Vector mapping INSN_UIDs to luids.
- ***************
- *** 97,107 ****
-
- rtx *loop_number_exit_labels;
-
- - /* Indexed by loop number, counts the number of LABEL_REFs on
- - loop_number_exit_labels for this loop and all loops nested inside it. */
- -
- - int *loop_number_exit_count;
- -
- /* Holds the number of loop iterations. It is zero if the number could not be
- calculated. Must be unsigned since the number of iterations can
- be as high as 2^wordsize-1. For loops with a wider iterator, this number
- --- 99,104 ----
- ***************
- *** 191,196 ****
- --- 188,196 ----
-
- static struct obstack temp_obstack;
-
- + /* intel1 */
- + extern struct obstack momentary_obstack;
- +
- /* This is where the pointer to the obstack being used for RTL is stored. */
-
- extern struct obstack *rtl_obstack;
- ***************
- *** 286,291 ****
- --- 286,349 ----
- static int last_use_this_basic_block ();
- static void record_initial ();
- static void update_reg_last_use ();
- + /* intel1 */
- + static int compare_elimination ();
- + static attempt_new_rtx ();
- + static rtx make_new_use ();
- + static int possible_compare_elimination ();
- + static void find_regs_mentioned ();
- + static void use_regs_source ();
- + static rtx replace_mems ();
- + static void replace_reg ();
- + static int two_to_power ();
- + static int jumps_back_in_loop ();
- + static loop_copy_propogate ();
- + static do_replace ();
- + static rtx subst_cands ();
- + static try_unroll_propogation ();
- + static rtx unroll_subst_cands ();
- + static unroll_consistancy_maintained ();
- + static int do_reduce_index ();
- + static loop_spl ();
- + void loop_after_global ();
- + static int spill_invariant_p ();
- + static void move_spills_out ();
- + static void move_spill_movables ();
- + static rtx subst_stack_slot ();
- + static int check_if_jumps_out_of_loop ();
- + static void mark_regs_alive_at_exit ();
- + static void verify_spill_candidates ();
- + static void mark_spill_candidates ();
- + static void spill_handle_regs_mentioned ();
- + static int is_updated_by_const ();
- + static int is_updated_by_const_or_reg ();
- + static void peep_init_info ();
- + static void spill_peep_insn ();
- + void update_stack_offset ();
- + static void replace_spill_slots ();
- + static rtx replace_linked_regs ();
- + static void mark_regs_live_outside ();
- + static void mark_regs_mentioned ();
- + static int loop_contains_loop ();
- + static void push_load_into_loop ();
- + static int spill_slot_unused_between ();
- + static int spill_slot_mentioned ();
- + void init_undo_buf ();
- + void subst_in_insn ();
- + static void inner_subst_in_insn ();
- + void loop_undo_all ();
- + static void update_last_reloads ();
- + static void sign_extension_reduction ();
- + static void validate_all_references ();
- + static void lift_stores ();
- + static void mark_mem_refs ();
- + static void insert_mem_ref ();
- + static void opt_reg_use_copy ();
- + int doing_spl = 0;
- + int doing_loop_after_global = 0;
- + static char * reg_live_outside_loop;
- + static int cur_stack_offset = 0;
- +
-
- /* Relative gain of eliminating various kinds of operations. */
- int add_cost;
- ***************
- *** 293,298 ****
- --- 351,360 ----
- int shift_cost;
- int mult_cost;
- #endif
- + /* intel1 maximum # of insns in loop for which compare elimination */
- + #ifndef MAX_CMP_ELIM
- + #define MAX_CMP_ELIM 100
- + #endif
-
- /* Benefit penalty, if a giv is not replaceable, i.e. must emit an insn to
- copy the value of the strength reduced giv to its original register. */
- ***************
- *** 341,346 ****
- --- 403,414 ----
-
- max_reg_before_loop = max_reg_num ();
-
- + /* intel1 */
- + #ifdef SAVE_ON_REGS
- + if (!flag_all_mem_givs && flag_opt_reg_use)
- + reg_live_outside_loop = (char *) alloca(max_reg_before_loop);
- + #endif
- +
- moved_once = (char *) alloca (max_reg_before_loop);
- bzero (moved_once, max_reg_before_loop);
-
- ***************
- *** 358,364 ****
-
- /* Don't waste time if no loops. */
- if (max_loop_num == 0)
- ! return;
-
- /* Get size to use for tables indexed by uids.
- Leave some space for labels allocated by find_and_verify_loops. */
- --- 426,442 ----
-
- /* Don't waste time if no loops. */
- if (max_loop_num == 0)
- ! {
- ! /* intel1 */
- ! #ifdef SAVE_ON_REGS
- ! if (!doing_loop_after_global && flag_opt_reg_use)
- ! {
- ! use_regs_source (f, NULL, 0);
- ! opt_reg_use_copy (f);
- ! }
- ! #endif
- ! return;
- ! }
-
- /* Get size to use for tables indexed by uids.
- Leave some space for labels allocated by find_and_verify_loops. */
- ***************
- *** 377,383 ****
- loop_outer_loop = (int *) alloca (max_loop_num * sizeof (int));
- loop_invalid = (char *) alloca (max_loop_num * sizeof (char));
- loop_number_exit_labels = (rtx *) alloca (max_loop_num * sizeof (rtx));
- - loop_number_exit_count = (int *) alloca (max_loop_num * sizeof (int));
-
- /* Find and process each loop.
- First, find them, and record them in order of their beginnings. */
- --- 455,460 ----
- ***************
- *** 386,392 ****
- /* Now find all register lifetimes. This must be done after
- find_and_verify_loops, because it might reorder the insns in the
- function. */
- ! reg_scan (f, max_reg_num (), 1);
-
- /* See if we went too far. */
- if (get_max_uid () > max_uid_for_loop)
- --- 463,470 ----
- /* Now find all register lifetimes. This must be done after
- find_and_verify_loops, because it might reorder the insns in the
- function. */
- ! /* intel1 Last paramater of reg_scan used to be 1. */
- ! reg_scan (f, max_reg_num (), !doing_loop_after_global);
-
- /* See if we went too far. */
- if (get_max_uid () > max_uid_for_loop)
- ***************
- *** 437,442 ****
- --- 515,557 ----
- scan_loop (loop_number_loop_starts[i], loop_number_loop_ends[i],
- max_reg_num ());
-
- + /* intel1 */
- + if (flag_strength_reduce && flag_copy_prop)
- + {
- + for (i = max_loop_num-1; i >= 0; i--)
- + {
- + if (! loop_invalid[i] && loop_number_loop_ends[i])
- + loop_copy_propogate (loop_number_loop_starts[i], loop_number_loop_ends[i]);
- + }
- + }
- + /* intel1 */
- + if ((flag_lift_stores || flag_runtime_lift_stores)
- + && !doing_loop_after_global)
- + {
- + for (i = max_loop_num-1; i >= 0; i--)
- + {
- + if (! loop_invalid[i] && loop_number_loop_ends[i])
- + lift_stores (loop_number_loop_starts[i], loop_number_loop_ends[i]);
- + }
- + }
- +
- + #ifdef SAVE_ON_REGS
- + if (!doing_loop_after_global && flag_opt_reg_use)
- + {
- + use_regs_source (f, NULL, 0);
- + opt_reg_use_copy (f);
- + }
- + #endif
- + /* intel1 */
- + #ifdef STORE_NOT_SET_CC0
- + #ifdef STACK_REGS
- + if (flag_sftwr_pipe && !doing_loop_after_global)
- + for (i = max_loop_num-1; i >= 0; i--)
- + {
- + loop_spl (loop_number_loop_starts[i], loop_number_loop_ends[i], i, 0);
- + }
- + #endif
- + #endif
- /* If debugging and unrolling loops, we must replicate the tree nodes
- corresponding to the blocks inside the loop, so that the original one
- to one mapping will remain. */
- ***************
- *** 493,501 ****
- --- 608,636 ----
- if it was used exactly once; contains const0_rtx if it was used more
- than once. */
- rtx *reg_single_usage = 0;
- +
- /* Nonzero if we are scanning instructions in a sub-loop. */
- int loop_depth = 0;
-
- + /* intel1 */
- + if (doing_loop_after_global
- + && !(GET_CODE (PREV_INSN (end)) == JUMP_INSN
- + && GET_CODE (NEXT_INSN (loop_start)) == CODE_LABEL
- + && JUMP_LABEL (PREV_INSN (end)) == NEXT_INSN (loop_start)
- + )
- + )
- + {
- + return;
- + }
- + #ifdef SAVE_ON_REGS
- + if (!flag_all_mem_givs && !doing_loop_after_global
- + && !loop_contains_loop (loop_start, end) && flag_opt_reg_use)
- + {
- + bzero (reg_live_outside_loop, max_reg_before_loop);
- + mark_regs_live_outside (loop_start, end);
- + }
- + #endif
- +
- n_times_set = (short *) alloca (nregs * sizeof (short));
- n_times_used = (short *) alloca (nregs * sizeof (short));
- may_not_optimize = (char *) alloca (nregs);
- ***************
- *** 591,597 ****
-
- count_loop_regs_set (loop_top ? loop_top : loop_start, end,
- may_not_optimize, reg_single_usage, &insn_count, nregs);
- !
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- may_not_optimize[i] = 1, n_times_set[i] = 1;
- bcopy ((char *) n_times_set, (char *) n_times_used, nregs * sizeof (short));
- --- 726,733 ----
-
- count_loop_regs_set (loop_top ? loop_top : loop_start, end,
- may_not_optimize, reg_single_usage, &insn_count, nregs);
- ! /* intel1 added if but not body */
- ! if (!doing_loop_after_global)
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- may_not_optimize[i] = 1, n_times_set[i] = 1;
- bcopy ((char *) n_times_set, (char *) n_times_used, nregs * sizeof (short));
- ***************
- *** 644,649 ****
- --- 780,787 ----
- in_libcall = 0;
-
- if (GET_CODE (p) == INSN
- + /* intel1 */
- + && (!doing_loop_after_global || GET_CODE(PATTERN(p)) == SET)
- && (set = single_set (p))
- && GET_CODE (SET_DEST (set)) == REG
- && ! may_not_optimize[REGNO (SET_DEST (set))])
- ***************
- *** 695,705 ****
- else if (! ((! maybe_never
- && ! loop_reg_used_before_p (set, p, loop_start,
- scan_start, end))
- ! || (! REG_USERVAR_P (SET_DEST (set))
- ! && ! REG_LOOP_TEST_P (SET_DEST (set)))
- || reg_in_basic_block_p (p, SET_DEST (set))))
- ;
- ! else if ((tem = invariant_p (src))
- && (dependencies == 0
- || (tem2 = invariant_p (dependencies)) != 0)
- && (n_times_set[REGNO (SET_DEST (set))] == 1
- --- 833,851 ----
- else if (! ((! maybe_never
- && ! loop_reg_used_before_p (set, p, loop_start,
- scan_start, end))
- ! || (!doing_loop_after_global
- ! && /* intel1 */!REG_USERVAR_P (SET_DEST (set))
- ! && ! REG_LOOP_TEST_P (SET_DEST (set)))
- || reg_in_basic_block_p (p, SET_DEST (set))))
- ;
- ! else if (((tem = invariant_p (src))
- ! /* intel1 */ || (doing_loop_after_global
- ! && RTX_IS_SPILL_P (p) == 1 && spill_invariant_p (src))
- ! )
- ! /* intel1 */
- ! && !(doing_loop_after_global
- ! && call_used_regs[REGNO (SET_DEST (set))]
- ! && loop_has_call)
- && (dependencies == 0
- || (tem2 = invariant_p (dependencies)) != 0)
- && (n_times_set[REGNO (SET_DEST (set))] == 1
- ***************
- *** 749,754 ****
- --- 895,901 ----
- might span a call. */
- && ! modified_between_p (SET_SRC (set), p,
- reg_single_usage[regno])
- + && !doing_loop_after_global /* intel1 */
- && no_labels_between_p (p, reg_single_usage[regno])
- && validate_replace_rtx (SET_DEST (set), SET_SRC (set),
- reg_single_usage[regno]))
- ***************
- *** 966,977 ****
- --- 1113,1137 ----
- move_movables (movables, threshold,
- insn_count, loop_start, end, nregs);
-
- + /* intel1 */
- + if (doing_loop_after_global && !loop_has_call)
- + {
- + move_spills_out(loop_start, end, nregs);
- + }
- /* Now candidates that still are negative are those not moved.
- Change n_times_set to indicate that those are not actually invariant. */
- for (i = 0; i < nregs; i++)
- if (n_times_set[i] < 0)
- n_times_set[i] = n_times_used[i];
-
- + /*intel1 */
- + #ifdef SAVE_ON_REGS
- + if (!doing_loop_after_global && flag_opt_reg_use)
- + {
- + use_regs_source(loop_start, end, 1);
- + }
- + #endif
- +
- if (flag_strength_reduce)
- strength_reduce (scan_start, end, loop_top,
- insn_count, loop_start, end);
- ***************
- *** 1257,1263 ****
- /* A reg used for zero-extending mustn't be eliminated. */
- && !m1->partial
- && (matched_regs[m1->regno]
- ! ||
- (
- /* Can combine regs with different modes loaded from the
- same constant only if the modes are the same or
- --- 1417,1423 ----
- /* A reg used for zero-extending mustn't be eliminated. */
- && !m1->partial
- && (matched_regs[m1->regno]
- ! ||
- (
- /* Can combine regs with different modes loaded from the
- same constant only if the modes are the same or
- ***************
- *** 1534,1539 ****
- --- 1694,1706 ----
- rtx end;
- int nregs;
- {
- + /* intel1 */
- + #ifdef SAVE_ON_REGS
- + rtx sinsn,last_sym;
- + int num_sym_adds;
- + #endif
- + /* intel1 */
- + int *insns_deleted;
- rtx new_start = 0;
- register struct movable *m;
- register rtx p;
- ***************
- *** 1548,1553 ****
- --- 1715,1760 ----
-
- num_movables = 0;
-
- + /* intel1 */
- + num_movables = 0;
- +
- + /* intel1 Any insn moved out of loop must be deleted from the log_links
- + of all other insns in the loop.
- + */
- + if (doing_loop_after_global)
- + {
- + insns_deleted = (int *) alloca ((max_uid_for_loop+1) * sizeof (int));
- + bzero(insns_deleted,(max_uid_for_loop+1) * sizeof (int));
- + }
- + /* intel1 */
- + #ifdef SAVE_ON_REGS
- + num_sym_adds=0;
- + last_sym = NULL;
- + for (sinsn=loop_start;flag_opt_reg_use && (sinsn!=end && num_sym_adds < 2);
- + sinsn=NEXT_INSN (sinsn))
- + {
- + if (GET_CODE (sinsn) == INSN
- + && GET_CODE (PATTERN (sinsn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (sinsn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (sinsn))) == PLUS
- + && GET_CODE (XEXP (SET_SRC (PATTERN (sinsn)), 0)) == REG
- + && GET_CODE (XEXP (SET_SRC (PATTERN (sinsn)), 1)) == SYMBOL_REF)
- + {
- + if (last_sym)
- + {
- + if (!rtx_equal_p (XEXP (SET_SRC (PATTERN (sinsn)), 1),
- + last_sym))
- + {
- + num_sym_adds++;
- + }
- + }
- + else
- + {
- + last_sym = XEXP (SET_SRC (PATTERN (sinsn)), 1);
- + }
- + }
- + }
- + #endif /* SAVE_ON_REGS */
- for (m = movables; m; m = m->next)
- {
- /* Describe this movable insn. */
- ***************
- *** 1626,1632 ****
-
- /* It is also desirable to move if it can be moved at no
- extra cost because something else was already moved. */
- !
- if (already_moved[regno]
- || (threshold * savings * m->lifetime) >= insn_count
- || (m->forces && m->forces->done
- --- 1833,1862 ----
-
- /* It is also desirable to move if it can be moved at no
- extra cost because something else was already moved. */
- ! #ifdef SAVE_ON_REGS
- ! /* intel1 if the insn is regx <- regy + symbol_ref then don't move
- ! if there is more than one.
- ! */
- ! if (flag_opt_reg_use
- ! && num_sym_adds > 1
- ! && GET_CODE (PATTERN (m->insn)) == SET
- ! && GET_CODE (SET_DEST (PATTERN (m->insn))) == REG
- ! && GET_CODE (SET_SRC (PATTERN (m->insn))) == PLUS
- ! && GET_CODE (XEXP (SET_SRC (PATTERN (m->insn)), 0)) == REG
- ! && GET_CODE (XEXP (SET_SRC (PATTERN (m->insn)), 1)) == SYMBOL_REF)
- ! {
- ! savings = 0;
- ! }
- ! #endif
- ! /* intel1 */
- ! #ifdef STACK_REGS
- ! #ifdef IS_STACK_MODE
- ! if (IS_STACK_MODE (DFmode)
- ! && GET_CODE (PATTERN (m->insn)) == SET
- ! && GET_CODE (SET_SRC (PATTERN (m->insn))) == CONST_DOUBLE)
- ! savings = 0; /* not worthwhile */
- ! #endif
- ! #endif
- if (already_moved[regno]
- || (threshold * savings * m->lifetime) >= insn_count
- || (m->forces && m->forces->done
- ***************
- *** 1659,1669 ****
- --- 1889,1912 ----
- regs_may_share = gen_rtx (EXPR_LIST, VOIDmode, r1,
- gen_rtx (EXPR_LIST, VOIDmode, r2,
- regs_may_share));
- + /* intel1 */
- + if (doing_loop_after_global
- + && INSN_UID (m->insn) <= max_uid_for_loop)
- + {
- + insns_deleted[INSN_UID (m->insn)] = 1;
- + }
- delete_insn (m->insn);
-
- if (new_start == 0)
- new_start = i1;
-
- + /* intel1 */
- + if (doing_loop_after_global)
- + {
- + RTX_IS_SPILL_P (i1) = RTX_IS_SPILL_P (m->insn);
- + SPILL_PSEUDO (i1) = SPILL_PSEUDO (m->insn);
- + }
- +
- if (loop_dump_stream)
- fprintf (loop_dump_stream, " moved to %d", INSN_UID (i1));
- }
- ***************
- *** 1690,1697 ****
- {
- temp = XEXP (temp, 0);
- while (temp != p)
- ! temp = delete_insn (temp);
- }
-
- p = delete_insn (p);
- while (p && GET_CODE (p) == NOTE)
- --- 1933,1954 ----
- {
- temp = XEXP (temp, 0);
- while (temp != p)
- ! {
- ! /* intel1 */
- ! if (doing_loop_after_global
- ! && INSN_UID( temp) <= max_uid_for_loop)
- ! {
- ! insns_deleted[INSN_UID( temp)] = 1;
- ! }
- ! temp = delete_insn (temp);
- ! }
- }
- + /* intel1 */
- + if (doing_loop_after_global
- + && INSN_UID( p) <= max_uid_for_loop)
- + {
- + insns_deleted[INSN_UID( p)] = 1;
- + }
-
- p = delete_insn (p);
- while (p && GET_CODE (p) == NOTE)
- ***************
- *** 1712,1717 ****
- --- 1969,1981 ----
- m->is_equiv ? REG_EQUIV : REG_EQUAL,
- m->set_src, REG_NOTES (i1));
-
- + /* intel1 */
- + if (doing_loop_after_global)
- + {
- + RTX_IS_SPILL_P (i1) = RTX_IS_SPILL_P (m->insn);
- + SPILL_PSEUDO (i1) = SPILL_PSEUDO (m->insn);
- + }
- +
- if (loop_dump_stream)
- fprintf (loop_dump_stream, " moved to %d", INSN_UID (i1));
-
- ***************
- *** 1813,1818 ****
- --- 2077,2088 ----
- if (temp == fn_address_insn)
- fn_address_insn = i1;
- REG_NOTES (i1) = REG_NOTES (temp);
- + /* intel1 */
- + if (doing_loop_after_global
- + && INSN_UID (temp) <= max_uid_for_loop)
- + {
- + insns_deleted[INSN_UID (temp)] = 1;
- + }
- delete_insn (temp);
- }
- }
- ***************
- *** 1868,1873 ****
- --- 2138,2150 ----
- if (new_start == 0)
- new_start = i1;
-
- + /* intel1 */
- + if (doing_loop_after_global)
- + {
- + RTX_IS_SPILL_P (i1) = RTX_IS_SPILL_P (m->insn);
- + SPILL_PSEUDO (i1) = SPILL_PSEUDO (m->insn);
- + }
- +
- if (loop_dump_stream)
- fprintf (loop_dump_stream, " moved to %d",
- INSN_UID (i1));
- ***************
- *** 1895,1900 ****
- --- 2172,2183 ----
- XEXP (temp, 0) = i1;
- }
-
- + /* intel1 */
- + if (doing_loop_after_global
- + && INSN_UID (p) <= max_uid_for_loop)
- + {
- + insns_deleted[INSN_UID (p)] = 1;
- + }
- delete_insn (p);
- do p = NEXT_INSN (p);
- while (p && GET_CODE (p) == NOTE);
- ***************
- *** 1959,1966 ****
- {
- for (temp = XEXP (temp, 0); temp != m1->insn;
- temp = NEXT_INSN (temp))
- ! delete_insn (temp);
- }
- delete_insn (m1->insn);
-
- /* Any other movable that loads the same register
- --- 2242,2263 ----
- {
- for (temp = XEXP (temp, 0); temp != m1->insn;
- temp = NEXT_INSN (temp))
- ! {
- ! /* intel1 */
- ! if (doing_loop_after_global
- ! && INSN_UID (temp) <= max_uid_for_loop)
- ! {
- ! insns_deleted[INSN_UID (temp)] = 1;
- ! }
- ! delete_insn (temp);
- ! }
- }
- + /* intel1 */
- + if (doing_loop_after_global
- + && INSN_UID (m1->insn) <= max_uid_for_loop)
- + {
- + insns_deleted[INSN_UID (m1->insn)] = 1;
- + }
- delete_insn (m1->insn);
-
- /* Any other movable that loads the same register
- ***************
- *** 1996,2001 ****
- --- 2293,2326 ----
- replace_regs (REG_NOTES (p), reg_map, nregs, 0);
- INSN_CODE (p) = -1;
- }
- + /* intel1 */
- + /* remove all deleted insns from the log_links of any insn in which
- + they appear */
- + if (doing_loop_after_global)
- + {
- + int i;
- + rtx rn,prev,link;
- +
- + for (rn=loop_start; rn!=end; rn=NEXT_INSN (rn))
- + {
- + if ((GET_CODE (rn) == INSN || GET_CODE (rn) == JUMP_INSN
- + || GET_CODE (rn) == CALL_INSN) && LOG_LINKS(rn))
- + {
- + for (prev = 0, link = LOG_LINKS (rn); link;
- + prev = link, link = XEXP (link, 1))
- + {
- + if (insns_deleted[INSN_UID(XEXP (link, 0))])
- + {
- + if (prev)
- + XEXP (prev, 1) = XEXP (link, 1);
- + else
- + LOG_LINKS (rn) = XEXP (link, 1);
- + }
- + }
- +
- + }
- + }
- + }
- }
-
- #if 0
- ***************
- *** 2246,2252 ****
- loop_outer_loop[next_loop] = current_loop;
- loop_invalid[next_loop] = 0;
- loop_number_exit_labels[next_loop] = 0;
- - loop_number_exit_count[next_loop] = 0;
- current_loop = next_loop;
- break;
-
- --- 2571,2576 ----
- ***************
- *** 2278,2283 ****
- --- 2602,2610 ----
- uid_loop_num[INSN_UID (insn)] = current_loop;
- }
-
- + /* This loop will be continued with NEXT_INSN (insn). */
- + insn = PREV_INSN (insn);
- +
- /* Any loop containing a label used in an initializer must be invalidated,
- because it can be jumped into from anywhere. */
-
- ***************
- *** 2291,2296 ****
- --- 2618,2634 ----
- loop_invalid[loop_num] = 1;
- }
-
- +
- + #if HAVE_movstricthi
- + if (flag_sign_extension_elim)
- + {
- + int i;
- + for (i = max_loop_num-1; i >= 0; i--)
- + if (! loop_invalid[i] && loop_number_loop_ends[i])
- + sign_extension_reduction (loop_number_loop_starts[i],
- + loop_number_loop_ends [i]);
- + }
- + #endif
- /* Now scan all insn's in the function. If any JUMP_INSN branches into a
- loop that it is not contained within, that loop is marked invalid.
- If any INSN or CALL_INSN uses a label's address, then the loop containing
- ***************
- *** 2304,2314 ****
- label in our loop and will simplify processing by both us and a
- possible second cse pass. */
-
- for (insn = f; insn; insn = NEXT_INSN (insn))
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- {
- int this_loop_num = uid_loop_num[INSN_UID (insn)];
- !
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
- {
- rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
- --- 2642,2653 ----
- label in our loop and will simplify processing by both us and a
- possible second cse pass. */
-
- +
- for (insn = f; insn; insn = NEXT_INSN (insn))
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- {
- int this_loop_num = uid_loop_num[INSN_UID (insn)];
- !
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
- {
- rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
- ***************
- *** 2338,2345 ****
- {
- rtx p;
- rtx our_next = next_real_insn (insn);
- - int dest_loop;
- - int outer_loop = -1;
-
- /* Go backwards until we reach the start of the loop, a label,
- or a JUMP_INSN. */
- --- 2677,2682 ----
- ***************
- *** 2351,2377 ****
- p = PREV_INSN (p))
- ;
-
- ! /* Check for the case where we have a jump to an inner nested
- ! loop, and do not perform the optimization in that case. */
- !
- ! if (JUMP_LABEL (insn))
- ! {
- ! dest_loop = uid_loop_num[INSN_UID (JUMP_LABEL (insn))];
- ! if (dest_loop != -1)
- ! {
- ! for (outer_loop = dest_loop; outer_loop != -1;
- ! outer_loop = loop_outer_loop[outer_loop])
- ! if (outer_loop == this_loop_num)
- ! break;
- ! }
- ! }
- !
- ! /* Make sure that the target of P is within the current loop. */
- !
- ! if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
- ! && uid_loop_num[INSN_UID (JUMP_LABEL (p))] != this_loop_num)
- ! outer_loop = this_loop_num;
- !
- /* If we stopped on a JUMP_INSN to the next insn after INSN,
- we have a block of code to try to move.
-
- --- 2688,2719 ----
- p = PREV_INSN (p))
- ;
-
- ! /* intel1 */
- ! if (flag_opt_jumps_out)
- ! {
- ! /* Retarget a jump around a sequence that contains jumps out
- ! of loop to jump out of the loop rather than jump around. */
- ! while (!(GET_CODE (p) == JUMP_INSN
- ! && JUMP_LABEL (p) != 0
- ! && condjump_p (p)
- ! && ! simplejump_p (p)
- ! && next_real_insn (JUMP_LABEL (p)) == our_next
- ! ) &&
- ! !(GET_CODE (p) == JUMP_INSN
- ! && (JUMP_LABEL (p) == 0
- ! || (uid_loop_num[INSN_UID (JUMP_LABEL (p))]
- ! == this_loop_num))
- ! )
- ! && GET_CODE (p) != CODE_LABEL
- ! && !(GET_CODE (p) == NOTE
- ! && NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
- ! && !(GET_CODE (p) == NOTE
- ! && NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)
- ! )
- ! {
- ! p = PREV_INSN (p);
- ! }
- ! }
- /* If we stopped on a JUMP_INSN to the next insn after INSN,
- we have a block of code to try to move.
-
- ***************
- *** 2381,2388 ****
- of the block, invert the jump in P and point it to that label,
- and move the block of code to the spot we found. */
-
- ! if (outer_loop == -1
- ! && GET_CODE (p) == JUMP_INSN
- && JUMP_LABEL (p) != 0
- /* Just ignore jumps to labels that were never emitted.
- These always indicate compilation errors. */
- --- 2723,2729 ----
- of the block, invert the jump in P and point it to that label,
- and move the block of code to the spot we found. */
-
- ! if (GET_CODE (p) == JUMP_INSN
- && JUMP_LABEL (p) != 0
- /* Just ignore jumps to labels that were never emitted.
- These always indicate compilation errors. */
- ***************
- *** 2407,2413 ****
- && uid_loop_num[INSN_UID (loc)] == target_loop_num)
- break;
-
- ! if (loc)
- {
- rtx cond_label = JUMP_LABEL (p);
- rtx new_label = get_label_after (p);
- --- 2748,2762 ----
- && uid_loop_num[INSN_UID (loc)] == target_loop_num)
- break;
-
- ! if (loc
- ! ||
- ! /* intel1 Enable the optimization even if no barier
- ! is found. This requires adding a jump
- ! around the section of code moved out - but
- ! this can win if jumps NOT taken are preferred.
- ! */
- ! (flag_opt_jumps_out
- ! && LABEL_NUSES (JUMP_LABEL (p)) == 1))
- {
- rtx cond_label = JUMP_LABEL (p);
- rtx new_label = get_label_after (p);
- ***************
- *** 2424,2430 ****
- /* Include the BARRIER after INSN and copy the
- block after LOC. */
- new_label = squeeze_notes (new_label, NEXT_INSN (insn));
- ! reorder_insns (new_label, NEXT_INSN (insn), loc);
-
- /* All those insns are now in TARGET_LOOP_NUM. */
- for (q = new_label; q != NEXT_INSN (NEXT_INSN (insn));
- --- 2773,2784 ----
- /* Include the BARRIER after INSN and copy the
- block after LOC. */
- new_label = squeeze_notes (new_label, NEXT_INSN (insn));
- ! /* intel1 */
- ! if (loc)
- ! reorder_insns (new_label, NEXT_INSN (insn), loc);
- ! else
- ! reorder_insns (new_label, NEXT_INSN (insn),
- ! PREV_INSN (target));
-
- /* All those insns are now in TARGET_LOOP_NUM. */
- for (q = new_label; q != NEXT_INSN (NEXT_INSN (insn));
- ***************
- *** 2438,2445 ****
- LABEL_OUTSIDE_LOOP_P bit. */
- if (JUMP_LABEL (insn))
- {
- - int loop_num;
- -
- for (q = 0,
- r = loop_number_exit_labels[this_loop_num];
- r; q = r, r = LABEL_NEXTREF (r))
- --- 2792,2797 ----
- ***************
- *** 2454,2464 ****
- break;
- }
-
- - for (loop_num = this_loop_num;
- - loop_num != -1 && loop_num != target_loop_num;
- - loop_num = loop_outer_loop[loop_num])
- - loop_number_exit_count[loop_num]--;
- -
- /* If we didn't find it, then something is wrong. */
- if (! r)
- abort ();
- --- 2806,2811 ----
- ***************
- *** 2468,2481 ****
- in loop_number_exit_labels, and marked as such.
- The easiest way to do this is to just call
- mark_loop_jump again for P. */
- mark_loop_jump (PATTERN (p), this_loop_num);
- !
- ! /* If INSN now jumps to the insn after it,
- ! delete INSN. */
- ! if (JUMP_LABEL (insn) != 0
- ! && (next_real_insn (JUMP_LABEL (insn))
- ! == next_real_insn (insn)))
- ! delete_insn (insn);
- }
-
- /* Continue the loop after where the conditional
- --- 2815,2838 ----
- in loop_number_exit_labels, and marked as such.
- The easiest way to do this is to just call
- mark_loop_jump again for P. */
- +
- mark_loop_jump (PATTERN (p), this_loop_num);
- ! /* intel1 */
- ! if (loc)
- ! {
- ! /* If INSN now jumps to the insn after it,
- ! delete INSN. */
- ! if (JUMP_LABEL (insn) != 0
- ! && (next_real_insn (JUMP_LABEL (insn))
- ! == next_real_insn (insn)))
- ! delete_insn (insn);
- ! }
- ! else
- ! {
- ! /* move the jump insn to just before the new_label */
- ! reorder_insns (insn, NEXT_INSN (insn),
- ! PREV_INSN (new_label));
- ! }
- }
-
- /* Continue the loop after where the conditional
- ***************
- *** 2484,2494 ****
- branch and hence needs no processing. */
- insn = NEXT_INSN (cond_label);
-
- ! if (--LABEL_NUSES (cond_label) == 0)
- ! delete_insn (cond_label);
- !
- ! /* This loop will be continued with NEXT_INSN (insn). */
- ! insn = PREV_INSN (insn);
- }
- }
- }
- --- 2841,2856 ----
- branch and hence needs no processing. */
- insn = NEXT_INSN (cond_label);
-
- ! /* intel1 */
- ! if (loc)
- ! {
- ! if (--LABEL_NUSES (cond_label) == 0)
- ! delete_insn (cond_label);
- ! }
- ! else
- ! {
- ! delete_insn (cond_label);
- ! }
- }
- }
- }
- ***************
- *** 2546,2573 ****
- mark this LABEL_REF so we know that this branch should predict
- false. */
-
- ! /* A check to make sure the label is not in an inner nested loop,
- ! since this does not count as a loop exit. */
- ! if (dest_loop != -1)
- ! {
- ! for (outer_loop = dest_loop; outer_loop != -1;
- ! outer_loop = loop_outer_loop[outer_loop])
- ! if (outer_loop == loop_num)
- ! break;
- ! }
- ! else
- ! outer_loop = -1;
- !
- ! if (loop_num != -1 && outer_loop == -1)
- {
- LABEL_OUTSIDE_LOOP_P (x) = 1;
- LABEL_NEXTREF (x) = loop_number_exit_labels[loop_num];
- loop_number_exit_labels[loop_num] = x;
- -
- - for (outer_loop = loop_num;
- - outer_loop != -1 && outer_loop != dest_loop;
- - outer_loop = loop_outer_loop[outer_loop])
- - loop_number_exit_count[outer_loop]++;
- }
-
- /* If this is inside a loop, but not in the current loop or one enclosed
- --- 2908,2918 ----
- mark this LABEL_REF so we know that this branch should predict
- false. */
-
- ! if (dest_loop != loop_num && loop_num != -1)
- {
- LABEL_OUTSIDE_LOOP_P (x) = 1;
- LABEL_NEXTREF (x) = loop_number_exit_labels[loop_num];
- loop_number_exit_labels[loop_num] = x;
- }
-
- /* If this is inside a loop, but not in the current loop or one enclosed
- ***************
- *** 2593,2599 ****
- --- 2938,2953 ----
- "\nLoop at %d ignored due to multiple entry points.\n",
- INSN_UID (loop_number_loop_starts[dest_loop]));
-
- + /* intel1
- + If doing loop_spl we don't care if there are multiple jumps
- + to the loop entry label. */
- + if (!doing_spl
- + || NEXT_INSN (loop_number_loop_starts[dest_loop])
- + != XEXP (x, 0))
- + {
- +
- loop_invalid[dest_loop] = 1;
- + }
- }
- return;
-
- ***************
- *** 2624,2636 ****
- as a branch out of this loop, but not into any loop. */
-
- if (loop_num != -1)
- ! {
- ! loop_number_exit_labels[loop_num] = x;
-
- - for (outer_loop = loop_num; outer_loop != -1;
- - outer_loop = loop_outer_loop[outer_loop])
- - loop_number_exit_count[outer_loop]++;
- - }
- return;
- }
- }
- --- 2978,2985 ----
- as a branch out of this loop, but not into any loop. */
-
- if (loop_num != -1)
- ! loop_number_exit_labels[loop_num] = x;
-
- return;
- }
- }
- ***************
- *** 2818,2824 ****
- return 1 + conditional;
- }
-
- -
- /* Return nonzero if all the insns in the loop that set REG
- are INSN and the immediately following insns,
- and if each of those insns sets REG in an invariant way
- --- 3167,3172 ----
- ***************
- *** 3047,3052 ****
- --- 3395,3416 ----
- may_not_move[regno] = 1;
- if (n_times_set[regno] < 127)
- ++n_times_set[regno];
- + /* intel1 */
- + if (doing_loop_after_global
- + && HARD_REGNO_NREGS (regno, GET_MODE (dest)) > 1)
- + { /* Count each hard reg in the group. */
- + register int i,next_regno;
- +
- + i = HARD_REGNO_NREGS (regno, GET_MODE (dest));
- + next_regno = regno + 1;
- + while (i!=1)
- + {
- + if (n_times_set[next_regno] < 127)
- + ++n_times_set[next_regno];
- + next_regno++;
- + i--;
- + }
- + }
- last_set[regno] = insn;
- }
- }
- ***************
- *** 3244,3249 ****
- --- 3608,3616 ----
- int call_seen;
- rtx test;
- rtx end_insert_before;
- + int try_compare_elimination, done_compare_elimination; /* intel1 */
- + rtx compare_insn, jump_insn, tinsn; /* intel1 */
- + int *times_reg_used; /* intel1 */
- int loop_depth = 0;
-
- reg_iv_type = (enum iv_mode *) alloca (max_reg_before_loop
- ***************
- *** 3373,3379 ****
- will be executed if the loop is executed. */
- && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop_top
- && ((NEXT_INSN (NEXT_INSN (p)) == loop_end && simplejump_p (p))
- ! || (NEXT_INSN (p) == loop_end && condjump_p (p)))))
- not_every_iteration = 1;
-
- else if (GET_CODE (p) == NOTE)
- --- 3740,3749 ----
- will be executed if the loop is executed. */
- && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop_top
- && ((NEXT_INSN (NEXT_INSN (p)) == loop_end && simplejump_p (p))
- ! || (NEXT_INSN (p) == loop_end && condjump_p (p))))
- ! /*intel1*/ && !(GET_CODE (p) == JUMP_INSN
- ! && jumps_back_in_loop(p,loop_start,0,0))
- ! )
- not_every_iteration = 1;
-
- else if (GET_CODE (p) == NOTE)
- ***************
- *** 3487,3492 ****
- --- 3857,3874 ----
- }
- }
-
- + /* Now see if it is wothwhile to do compare elimination, remember it only
- + saves one instruction. intel1
- + */
- + try_compare_elimination = 0;
- + if (flag_compare_elim
- + && loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]] == NULL)
- + {
- + possible_compare_elimination(loop_start, loop_end, &compare_insn,
- + &jump_insn, &try_compare_elimination);
- + done_compare_elimination = 0;
- + }
- +
- /* Look at the each biv and see if we can say anything better about its
- initial value from any initializing insns set up above. (This is done
- in two passes to avoid missing SETs in a PARALLEL.) */
- ***************
- *** 3508,3513 ****
- --- 3890,3910 ----
- || GET_MODE (src) == VOIDmode)
- && valid_initial_value_p (src, bl->init_insn, call_seen, loop_start))
- {
- + /* intel1 */
- + if (flag_compare_elim && !flag_unroll_loops
- + && try_compare_elimination && !done_compare_elimination
- + && bl->biv_count == 1
- + && bl->biv->mult_val == const1_rtx
- + && REGNO (XEXP (SET_SRC (PATTERN (compare_insn)), 0)) == bl->regno
- + && (done_compare_elimination
- + = compare_elimination (bl, loop_start, loop_end,
- + compare_insn, jump_insn,0)))
- + {
- + rtx tem = find_reg_note (bl->init_insn, REG_EQUAL, 0);
- + if (tem)
- + XEXP (tem, 0) = SET_SRC (bl->init_set);
- + src = SET_SRC (bl->init_set);
- + }
- bl->initial_value = src;
-
- if (loop_dump_stream)
- ***************
- *** 3651,3657 ****
- will be executed if the loop is executed. */
- && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop_top
- && ((NEXT_INSN (NEXT_INSN (p)) == loop_end && simplejump_p (p))
- ! || (NEXT_INSN (p) == loop_end && condjump_p (p)))))
- not_every_iteration = 1;
-
- else if (GET_CODE (p) == NOTE)
- --- 4048,4057 ----
- will be executed if the loop is executed. */
- && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop_top
- && ((NEXT_INSN (NEXT_INSN (p)) == loop_end && simplejump_p (p))
- ! || (NEXT_INSN (p) == loop_end && condjump_p (p))))
- ! /*intel1*/ && !(GET_CODE (p) == JUMP_INSN
- ! && jumps_back_in_loop(p,loop_start,0,0))
- ! )
- not_every_iteration = 1;
-
- else if (GET_CODE (p) == NOTE)
- ***************
- *** 3717,3722 ****
- --- 4117,4128 ----
- for (bl = loop_iv_list; bl; bl = bl->next)
- {
- struct induction *v;
- + /* intel1 */
- + #ifdef SAVE_ON_REGS
- + int num_add_vals_live_outside =0;
- + int no_mem_givs = 0;
- + int contains_loop =0;
- + #endif
- int benefit;
- int all_reduced;
- rtx final_value = 0;
- ***************
- *** 3774,3779 ****
- --- 4180,4276 ----
- We can't (currently) eliminate the biv unless this is so. */
- all_reduced = 1;
-
- + /* intel1 */
- + #ifdef SAVE_ON_REGS
- + /* Only reduce DEST_ADDR givs of this biv if they will not increase
- + register pressure.
- + */
- + if (!flag_all_mem_givs && flag_opt_reg_use)
- + {
- + int num_mult_val_saved = 0;
- + int num_givs_to_update = 0;
- + num_add_vals_live_outside = 0;
- + no_mem_givs = 0;
- + contains_loop = loop_contains_loop (loop_start, end);
- +
- + for (v = bl->giv; v; v = v->next_iv)
- + {
- + if (v->giv_type == DEST_ADDR)
- + num_mult_val_saved++;
- + if (v->giv_type == DEST_ADDR && !v->same)
- + {
- + num_givs_to_update++;
- + if (v->add_val && GET_CODE (v->add_val) == REG
- + && REGNO (v->add_val) >= FIRST_PSEUDO_REGISTER
- + && (contains_loop
- + || REGNO (v->add_val)<max_reg_before_loop))
- + {
- + if (loop_dump_stream
- + && reg_live_outside_loop[REGNO (v->add_val)])
- + {
- + fprintf (loop_dump_stream,
- + "dest addr giv at %d has add_val live outside reg%d\n",
- + INSN_UID (v->insn), REGNO (v->add_val));
- + }
- + if (contains_loop)
- + num_add_vals_live_outside += 2;
- + else
- + {
- + num_add_vals_live_outside +=
- + reg_live_outside_loop[REGNO (v->add_val)];
- + }
- + }
- + else if (v->add_val && GET_CODE (v->add_val) == CONST_INT
- + && v->mult_val == const1_rtx)
- + { /* Disable this reduction. */
- + num_add_vals_live_outside = (1 << ((sizeof (int)*8)-4));
- + }
- + }
- + }
- + #ifdef MAX_DEST_ADDR_GIVS
- + if (num_givs_to_update > MAX_DEST_ADDR_GIVS)
- + {
- + no_mem_givs = 1;
- + }
- + #endif
- + /* Heuristic here:
- + a) If the biv is eliminated that saves one register in the loop.
- + b) Each giv_to_update must be updated at the end of the loop.
- + c) Each add_val_live_outside may cause a spill somewhere.
- + */
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream,
- + "eliminable %d num_updates %d mults_saved %d adds_outside %d heu %d\n",
- + bl->eliminable, num_givs_to_update, num_mult_val_saved,
- + num_add_vals_live_outside,
- + (((int)(bl->eliminable) * -3)
- + + (num_givs_to_update+((int)(bl->eliminable) * -1))
- + + (num_mult_val_saved*-1) +
- + + (num_add_vals_live_outside*3)
- + ));
- + }
- + if (no_mem_givs
- + ||
- + (((int)(bl->eliminable) * -3)
- + + (num_givs_to_update+((int)(bl->eliminable) * -1))
- + + (num_mult_val_saved*-1) +
- + + (num_add_vals_live_outside*3) > 0
- + )
- + )
- + {
- + all_reduced = 0;
- + for (v = bl->giv; v; v = v->next_iv)
- + {
- + if (v->giv_type == DEST_ADDR)
- + {
- + v->ignore = 1;
- + }
- + }
- + }
- + }
- + #endif /* SAVE_ON_REGS */
- +
- /* Check each giv in this class to see if we will benefit by reducing
- it. Skip giv's combined with others. */
- for (v = bl->giv; v; v = v->next_iv)
- ***************
- *** 3965,3971 ****
- loop to ensure that it will always be executed no matter
- how the loop exits. Otherwise, emit the insn after the loop,
- since this is slightly more efficient. */
- ! if (loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]])
- insert_before = loop_start;
- else
- insert_before = end_insert_before;
- --- 4462,4468 ----
- loop to ensure that it will always be executed no matter
- how the loop exits. Otherwise, emit the insn after the loop,
- since this is slightly more efficient. */
- ! if (loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]])
- insert_before = loop_start;
- else
- insert_before = end_insert_before;
- ***************
- *** 4032,4037 ****
- --- 4529,4542 ----
- of the occurrences of the biv with a giv, but no harm was done in
- doing so in the rare cases where it can occur. */
-
- + /* intel1 Retry compare elimination this time for loop trip test. */
- + if (flag_compare_elim && !flag_unroll_loops
- + && !done_compare_elimination && bl->retry_celim > 1
- + && all_reduced == 1 && bl->eliminable)
- + {
- + compare_elimination (bl, loop_start, loop_end,
- + compare_insn, jump_insn, 1);
- + }
- if (all_reduced == 1 && bl->eliminable
- && maybe_eliminate_biv (bl, loop_start, end, 1,
- threshold, insn_count))
- ***************
- *** 4057,4063 ****
- loop to ensure that it will always be executed no matter
- how the loop exits. Otherwise, emit the insn after the
- loop, since this is slightly more efficient. */
- ! if (loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]])
- insert_before = loop_start;
- else
- insert_before = end_insert_before;
- --- 4562,4568 ----
- loop to ensure that it will always be executed no matter
- how the loop exits. Otherwise, emit the insn after the
- loop, since this is slightly more efficient. */
- ! if (loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]])
- insert_before = loop_start;
- else
- insert_before = end_insert_before;
- ***************
- *** 4083,4088 ****
- --- 4588,4606 ----
- fprintf (loop_dump_stream, "Reg %d: biv eliminated\n",
- bl->regno);
- }
- + /* intel1 Retry compare elimination this time handling ashifhts. */
- + else if (flag_compare_elim && !flag_unroll_loops
- + && !done_compare_elimination && bl->retry_celim == 1)
- + {
- + if (compare_elimination (bl, loop_start, loop_end,
- + compare_insn, jump_insn, 1))
- + {
- + rtx tem = find_reg_note (bl->init_insn, REG_EQUAL, 0);
- + if (tem)
- + XEXP (tem, 0) = SET_SRC (bl->init_set);
- + bl->initial_value = SET_SRC (bl->init_set);;
- + }
- + }
- }
-
- /* Go through all the instructions in the loop, making all the
- ***************
- *** 4164,4169 ****
- --- 4682,4689 ----
- register int i, j;
- register enum rtx_code code;
- register char *fmt;
- + /* intel1 */
- + rtx tx;
-
- if (x == 0)
- return;
- ***************
- *** 4195,4200 ****
- --- 4715,4738 ----
- benefit = general_induction_var (XEXP (x, 0),
- &src_reg, &add_val, &mult_val);
-
- + /* intel1
- + For now lets strip off consty and try to recoginze the result
- + as a possible mem_giv. */
- + #ifdef REWRITE_ADDRESS
- + if (flag_opt_reg_use
- + && benefit == 0 && GET_CODE (XEXP (x, 0)) == PLUS
- + && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
- + && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- + || GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST
- + || GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF))
- + {
- + tx = x;
- + x = XEXP (x, 0);
- + benefit = general_induction_var (XEXP (x, 0),
- + &src_reg, &add_val, &mult_val);
- + }
- + #endif
- +
- /* Don't make a DEST_ADDR giv with mult_val == 1 && add_val == 0.
- Such a giv isn't useful. */
- if (benefit > 0 && (mult_val != const1_rtx || add_val != const0_rtx))
- ***************
- *** 4203,4208 ****
- --- 4741,4765 ----
- struct induction *v
- = (struct induction *) oballoc (sizeof (struct induction));
-
- + /* intel1 */
- + #ifdef REDUCE_INDEX
- + #ifdef REWRITE_ADDRESS
- + #ifdef LEGITIMATE_INDEX_P
- + rtx * index_part;
- + /* try to eliminate index terms */
- + if (REDUCE_INDEX && flag_reduce_index_givs
- + && do_reduce_index (x, &add_val))
- + {
- + index_part = &XEXP (XEXP (x, 0), 0);
- + record_giv (v, insn, src_reg, addr_placeholder, mult_val,
- + add_val, benefit, DEST_ADDR, not_every_iteration,
- + index_part, loop_start, loop_end);
- + v->is_index_induc = 1;
- + }
- + else
- + #endif
- + #endif
- + #endif
- record_giv (v, insn, src_reg, addr_placeholder, mult_val,
- add_val, benefit, DEST_ADDR, not_every_iteration,
- &XEXP (x, 0), loop_start, loop_end);
- ***************
- *** 4290,4295 ****
- --- 4847,4854 ----
- bl->eliminable = 0;
- bl->nonneg = 0;
- bl->reversed = 0;
- + /* intel1 */
- + bl->retry_celim = 0;
- bl->total_benefit = 0;
-
- /* Add this class to loop_iv_list. */
- ***************
- *** 4374,4379 ****
- --- 4933,4942 ----
- v->new_reg = 0;
- v->final_value = 0;
- v->same_insn = 0;
- + /* intel1 */
- + #ifdef REDUCE_INDEX
- + v->is_index_induc = 0;
- + #endif
-
- /* The v->always_computable field is used in update_giv_derive, to
- determine whether a giv can be used to derive another giv. For a
- ***************
- *** 4651,4657 ****
-
- if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
- && LABEL_NAME (JUMP_LABEL (p))
- ! && ((INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (v->insn)
- && INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (loop_start))
- || (INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (last_giv_use)
- && INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (loop_end))))
- --- 5214,5221 ----
-
- if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
- && LABEL_NAME (JUMP_LABEL (p))
- ! && ( INSN_UID(v->insn)>=max_uid_for_loop /* intel1 */
- ! || (INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (v->insn)
- && INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (loop_start))
- || (INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (last_giv_use)
- && INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (loop_end))))
- ***************
- *** 5474,5482 ****
- the expression of G2 in terms of G1 can be used. */
- if (g2->giv_type == DEST_ADDR
- && (tem = express_from (g1, g2)) != 0
- && memory_address_p (g2->mem_mode, tem)
- ! && ADDRESS_COST (tem) <= ADDRESS_COST (*g2->location))
- {
- g2->new_reg = tem;
- return 1;
- }
- --- 6038,6063 ----
- the expression of G2 in terms of G1 can be used. */
- if (g2->giv_type == DEST_ADDR
- && (tem = express_from (g1, g2)) != 0
- + /* intel1 */
- + #ifdef REDUCE_INDEX
- + && ((g2->is_index_induc && LEGITIMATE_INDEX_P(tem))
- + || (g2->is_index_induc == 0 && memory_address_p (g2->mem_mode, tem)
- + && ADDRESS_COST (tem) <= ADDRESS_COST (*g2->location))
- + )
- + #else
- && memory_address_p (g2->mem_mode, tem)
- ! && ADDRESS_COST (tem) <= ADDRESS_COST (*g2->location)
- ! #endif
- ! )
- {
- + /* intel1 */
- + #ifdef SAVE_ON_REGS
- +
- + if (flag_opt_reg_use && ADDRESS_COST (tem) != 1)
- + {
- + return(0);
- + }
- + #endif
- g2->new_reg = tem;
- return 1;
- }
- ***************
- *** 5772,5778 ****
- num_nonfixed_reads += count_nonfixed_reads (PATTERN (p));
-
- if (bl->giv_count == 0
- ! && ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]])
- {
- rtx bivreg = regno_reg_rtx[bl->regno];
-
- --- 6353,6359 ----
- num_nonfixed_reads += count_nonfixed_reads (PATTERN (p));
-
- if (bl->giv_count == 0
- ! && ! loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]])
- {
- rtx bivreg = regno_reg_rtx[bl->regno];
-
- ***************
- *** 6274,6279 ****
- --- 6855,6869 ----
- for (v = bl->giv; v; v = v->next_iv)
- if (v->giv_type == DEST_ADDR && v->location == &XEXP (x, 0))
- return 1;
- + /* intel1 */
- + #ifdef REDUCE_INDEX
- + #ifdef LEGITIMATE_INDEX_P
- + for (v = bl->giv; v; v = v->next_iv)
- + if (REDUCE_INDEX && v->giv_type == DEST_ADDR && v->is_index_induc
- + && v->location == &XEXP (XEXP(x,0), 0))
- + return 1;
- + #endif
- + #endif
- break;
- }
-
- ***************
- *** 6628,6631 ****
- --- 7218,13765 ----
-
- return gen_rtx (swap_condition (GET_CODE (comparison)), VOIDmode,
- XEXP (comparison, 1), XEXP (comparison, 0));
- + }
- +
- + /* new code added by intel1 */
- + struct new_rtx
- + {
- + rtx pat;
- + rtx insn;
- + rtx supplemental_pat; /* Pattern that should be
- + emited after this insn. */
- + struct new_rtx *next;
- + };
- +
- + /* If bl is also the loop counter try to optimize out the
- + compare instruction by counting up to 0. Return 1 if
- + successful.
- + */
- + static
- + int
- + compare_elimination (bl, loop_start, loop_end, compare_insn, jump_insn, second_time)
- + struct iv_class *bl;
- + rtx loop_start, loop_end, compare_insn, jump_insn;
- + int second_time;
- + {
- + rtx insn, new_init_src, copy_of_jump, new_biv_set, loop_trip_reg;
- + int init_val, compare_val, i, adjust_val, desired_init_val;
- + int num_times_loop_execs, add_one, biv_init_to_const, biv_end_value;
- + int num_sups, compare_to_const;
- + struct new_rtx *new_rtx_element, *new_rtx_head, *new_rtx_tail;
- + char *storage;
- +
- +
- + if (GET_CODE (SET_DEST (bl->init_set)) != REG)
- + {
- + return (0);
- + }
- + if (!rtx_equal_p (SET_DEST (bl->init_set),
- + XEXP (SET_SRC (PATTERN (compare_insn)), 0))
- + )
- + {
- + return (0);
- + }
- + copy_of_jump = copy_rtx (PATTERN (jump_insn));
- + PUT_CODE (XEXP (SET_SRC (copy_of_jump), 0), NE);
- + if (recog (copy_of_jump, jump_insn, 0) == -1)
- + {
- + return (0);
- + }
- + if (GET_CODE (XEXP (SET_SRC (PATTERN (compare_insn)), 1)) == CONST_INT)
- + {
- + if (bl->initial_test != NULL)
- + {
- + return (0);
- + }
- + compare_val = INTVAL (XEXP (SET_SRC (PATTERN (compare_insn)), 1));
- + compare_to_const = 1;
- + }
- + else
- + {
- + compare_to_const = 0;
- + if (INTVAL (bl->biv->add_val) != 1)
- + {
- + return (0);
- + }
- + else if (second_time == 0)
- + {
- + bl->retry_celim = 2; /* Signals that this is loop trip test
- + candidate. */
- + return (0);
- + }
- + }
- + if (GET_CODE (SET_SRC (bl->init_set)) != CONST_INT)
- + {
- + if (!compare_to_const)
- + {
- + return (0);
- + }
- + else
- + {
- + if (abs (INTVAL (bl->biv->add_val)) != 1)
- + {
- + return (0);
- + }
- + biv_init_to_const = 0;
- + /* Just so checks on LE GE ... pass. */
- + init_val = compare_val - INTVAL (bl->biv->add_val);
- + }
- + }
- + else
- + {
- + init_val = INTVAL (SET_SRC (bl->init_set));
- + biv_init_to_const = 1;
- + }
- + insn = PREV_INSN (compare_insn);
- + while (GET_CODE (insn) == NOTE)
- + {
- + insn = PREV_INSN (insn);
- + }
- + if (!(GET_CODE (insn) == INSN
- + && rtx_equal_p (SET_DEST (PATTERN (insn)), SET_DEST (bl->init_set))
- + && bl->biv->insn == insn))
- + {
- + return (0);
- + }
- + switch (GET_CODE (XEXP (SET_SRC (PATTERN (jump_insn)), 0)))
- + {
- + case LE:
- + if (compare_to_const
- + && (INTVAL (bl->biv->add_val) <= 0 || compare_val < init_val))
- + {
- + return (0);
- + }
- + add_one = 1;
- + break;
- +
- + case GE:
- + if (compare_to_const
- + && (INTVAL (bl->biv->add_val) >= 0 || compare_val > init_val))
- + {
- + return (0);
- + }
- + add_one = 1;
- + break;
- +
- + case LT:
- + if (compare_to_const
- + && (INTVAL (bl->biv->add_val) <= 0 || compare_val <= init_val))
- + {
- + return (0);
- + }
- + add_one = 0;
- + break;
- +
- + case GT:
- + if (compare_to_const
- + && (INTVAL (bl->biv->add_val) >= 0 || compare_val >= init_val))
- + {
- + return (0);
- + }
- + add_one = 0;
- + break;
- +
- + default:
- + return (0);
- + }
- + if (!compare_to_const)
- + { /* We are doing loop trip test. */
- + if (n_times_set[REGNO (XEXP (SET_SRC (PATTERN (compare_insn)), 1))])
- + {
- + return (0);
- + }
- + loop_trip_reg = gen_reg_rtx (GET_MODE (SET_DEST (bl->init_set)));
- + desired_init_val = (-1 * init_val) + add_one;
- + /* Emit insn to initialize loop trip reg. */
- + if (desired_init_val)
- + {
- + emit_insn_before (gen_rtx (SET, 0, loop_trip_reg,
- + gen_rtx (PLUS, GET_MODE (loop_trip_reg),
- + XEXP (SET_SRC (PATTERN (compare_insn)), 1),
- + gen_rtx (CONST_INT, 0, desired_init_val))),
- + loop_start);
- + }
- + else
- + {
- + emit_insn_before (gen_rtx (SET, 0, loop_trip_reg,
- + XEXP (SET_SRC (PATTERN (compare_insn)), 1)),
- + loop_start);
- + }
- + /* Emit insn to decrement loop trip reg. */
- + emit_insn_before (gen_rtx (SET, 0, loop_trip_reg,
- + gen_rtx (PLUS, GET_MODE (loop_trip_reg),
- + loop_trip_reg,
- + gen_rtx (CONST_INT, 0, -1))),
- + compare_insn);
- + /* Change comparison */
- + XEXP (SET_SRC (PATTERN (compare_insn)), 1) = const0_rtx;
- + XEXP (SET_SRC (PATTERN (compare_insn)), 0) = loop_trip_reg;
- + /* Change jump insn */
- + PUT_CODE (XEXP (SET_SRC (PATTERN (jump_insn)), 0), NE);
- + INSN_CODE (jump_insn) = recog (PATTERN (jump_insn), jump_insn, 0);
- + bl->retry_celim = 0;
- + return (1);
- + }
- + if (biv_init_to_const)
- + {
- + num_times_loop_execs
- + = ((abs (compare_val - init_val) + add_one - 1) / abs (INTVAL (bl->biv->add_val))) + 1;
- + desired_init_val = -1 * num_times_loop_execs * INTVAL (bl->biv->add_val);
- + adjust_val = init_val - desired_init_val;
- + new_init_src = gen_rtx (CONST_INT, 0, desired_init_val);
- +
- + biv_end_value = num_times_loop_execs * INTVAL (bl->biv->add_val) + init_val;
- +
- + }
- + else
- + {/* biv is incremented by +-1 so the adjust_val is */
- + adjust_val
- + = (compare_val + (add_one * INTVAL (bl->biv->add_val)));
- + desired_init_val = -1 * adjust_val;
- + biv_end_value = compare_val + (add_one * INTVAL (bl->biv->add_val));
- + /* Make a check that we will be able to adjust the bivs init_val
- + by desired_init_val. */
- + new_init_src = gen_rtx (PLUS, GET_MODE (SET_DEST (bl->init_set)),
- + SET_SRC (bl->init_set),
- + gen_rtx (CONST_INT, 0, desired_init_val));
- + new_biv_set = gen_rtx (SET, GET_MODE (SET_SRC (bl->init_set)),
- + SET_DEST (bl->init_set), new_init_src);
- + if (recog (new_biv_set, bl->init_set, 0) == -1)
- + {
- + return (0);
- + }
- + }
- + /* Now see if we can replace register bl->regno with
- + bl->regno+(adjust_val) in all insns from bl->init_insn to
- + loop_end.
- + Signal that if we fail we should retry again at the end of
- + strength reduction. */
- + if (second_time == 0)
- + {
- + bl->retry_celim = 1;
- + }
- + /* Mark our place on the obstack in case of failure. */
- + storage = (char *) oballoc (0);
- + num_sups = 0;
- + new_rtx_head = new_rtx_tail = NULL;
- + insn = NEXT_INSN (bl->init_insn);
- + while (insn != compare_insn)
- + {
- + if (GET_CODE (insn) == INSN
- + && !rtx_equal_p (SET_DEST (PATTERN (insn)), SET_DEST (bl->init_set)))
- + {
- + new_rtx_element = (struct new_rtx *) alloca (sizeof (struct new_rtx));
- + new_rtx_element->insn = insn;
- + new_rtx_element->supplemental_pat = NULL;
- + if (!attempt_new_rtx (new_rtx_element, insn, bl, adjust_val, second_time))
- + {
- + obfree (storage);
- + return (0);
- + }
- + else if (!rtx_equal_p (SET_SRC (insn), SET_SRC (new_rtx_element->pat))
- + || !rtx_equal_p (SET_DEST (insn), SET_DEST (new_rtx_element->pat)))
- + {
- + if (new_rtx_head == NULL)
- + {
- + new_rtx_head = new_rtx_element;
- + }
- + else
- + {
- + new_rtx_tail->next = new_rtx_element;
- + }
- + new_rtx_tail = new_rtx_element;
- + new_rtx_element->next = 0;
- + }
- + if (new_rtx_element->supplemental_pat)
- + {
- + num_sups++;
- + if (num_sups > 3)
- + { /* heuristic */
- + obfree (storage);
- + return (0);
- + }
- + }
- + }
- + insn = NEXT_INSN (insn);
- + }
- + /* Replacement can be done now do it. */
- + new_rtx_element = new_rtx_head;
- + while (new_rtx_element)
- + {
- + PATTERN (new_rtx_element->insn) = new_rtx_element->pat;
- + if (new_rtx_element->supplemental_pat)
- + {
- + emit_insn_after (
- + gen_move_insn (SET_DEST (new_rtx_element->supplemental_pat),
- + SET_SRC (new_rtx_element->supplemental_pat)),
- + new_rtx_element->insn);
- + }
- + new_rtx_element = new_rtx_element->next;
- + }
- + /* Finally update the initialization and comparison of the biv. */
- + PUT_CODE (XEXP (SET_SRC (PATTERN (jump_insn)), 0), NE);
- + INSN_CODE (jump_insn) = recog (PATTERN (jump_insn), jump_insn, 0);
- + XEXP (SET_SRC (PATTERN (compare_insn)), 1) = const0_rtx;
- + SET_SRC (bl->init_set) = new_init_src;
- + INSN_CODE (bl->init_insn) = recog ( PATTERN (bl->init_insn), bl->init_insn, 0);
- + emit_insn_after (gen_rtx (SET, GET_MODE (SET_DEST (bl->init_set)),
- + SET_DEST (bl->init_set),
- + gen_rtx (CONST_INT, 0, biv_end_value)),
- + loop_end);
- + bl->retry_celim = 0;
- + return (1);
- +
- + }
- +
- + /* Try to rewrite insn replacing the biv with biv+biv_adjust_const. if
- + the substitution is not immediately recognizable then try to
- + rewrite the insn to make it recognizable. If try_supplemental is 1
- + then an additional insn may be generated to make the substitution
- + recognizable. The generated pattern is pointed to by
- + new_rtx_element->pat.
- + */
- + static
- + attempt_new_rtx (new_rtx_element, insn, bl, biv_adjust_const, try_supplemental)
- + rtx insn;
- + struct new_rtx *new_rtx_element;
- + struct iv_class *bl;
- + int biv_adjust_const;
- + int try_supplemental;
- + {
- + rtx new_src, new_dest, make_new_use (), try_to_make_good ();
- +
- + new_src
- + = make_new_use (SET_SRC (PATTERN (insn)), SET_DEST (bl->init_set),
- + biv_adjust_const, insn);
- + new_dest
- + = make_new_use (SET_DEST (PATTERN (insn)), SET_DEST (bl->init_set),
- + biv_adjust_const, insn);
- + new_rtx_element->pat = gen_rtx (SET, 0, new_dest, new_src);
- + if (recog (new_rtx_element->pat, insn, 0) < 0)
- + {
- + try_to_make_good (SET_SRC (new_rtx_element->pat));
- + try_to_make_good (SET_DEST (new_rtx_element->pat));
- + }
- + if (recog (new_rtx_element->pat, insn, 0) < 0)
- + {
- + if (!try_supplemental)
- + {
- + return (0);
- + }
- + if (GET_CODE (SET_DEST (new_rtx_element->pat)) == REG
- + && GET_CODE (SET_SRC (new_rtx_element->pat)) == ASHIFT
- + && GET_CODE (XEXP (SET_SRC (new_rtx_element->pat), 0)) == PLUS
- + && GET_CODE (XEXP (SET_SRC (new_rtx_element->pat), 1)) == CONST_INT
- + && GET_CODE (XEXP (XEXP (SET_SRC (new_rtx_element->pat), 0), 0)) == REG
- + && GET_CODE (XEXP (XEXP (SET_SRC (new_rtx_element->pat), 0), 1)) == CONST_INT
- + )
- + {
- + /* try to rewrite:
- + (set (reg:SI x)
- + (ashift:SI (plus:SI (reg/v:SI y)
- + (const_int a))
- + (const_int b)))
- +
- + into two patterns:
- + (set (reg:SI x)
- + (ashift:SI (reg/v:SI y)
- + (const_int b)))
- +
- + (set (reg:SI x)
- + (plus:SI (reg/v:SI x)
- + (const_int a*(2**b))))
- + */
- + int add_val;
- + add_val
- + = two_to_power (INTVAL (XEXP (SET_SRC (new_rtx_element->pat), 1)))
- + * INTVAL (XEXP (XEXP (SET_SRC (new_rtx_element->pat), 0), 1));
- + new_rtx_element->pat = PATTERN (new_rtx_element->insn);
- + new_rtx_element->supplemental_pat
- + = gen_rtx (SET, GET_MODE (SET_DEST (new_rtx_element->pat)),
- + SET_DEST (new_rtx_element->pat),
- + gen_rtx (PLUS, GET_MODE (XEXP (SET_SRC (new_rtx_element->pat), 0)),
- + SET_DEST (new_rtx_element->pat),
- + gen_rtx (CONST_INT, 0, add_val)));
- + }
- + else if (GET_CODE (SET_DEST (new_rtx_element->pat)) == REG
- + && GET_CODE (SET_SRC (new_rtx_element->pat)) == PLUS
- + && GET_CODE (XEXP (SET_SRC (new_rtx_element->pat), 0)) == REG
- + && GET_CODE (XEXP (SET_SRC (new_rtx_element->pat), 1)) == PLUS
- + && GET_CODE (XEXP (XEXP (SET_SRC (new_rtx_element->pat), 1), 0)) == REG
- + && GET_CODE (XEXP (XEXP (SET_SRC (new_rtx_element->pat), 1), 1)) == CONST_INT
- + )
- + {
- + /* try to rewrite:
- + (set (reg:SI x)
- + (plus:SI (reg:SI y)
- + (plus:SI (reg:SI z)
- + (const_int a))))
- +
- + into two patterns:
- + (set (reg:SI x)
- + (plus:SI (reg/v:SI y)
- + (reg/v:SI z)))
- +
- + (set (reg:SI x)
- + (plus:SI (reg/v:SI x)
- + (const_int a)))
- + */
- + new_rtx_element->supplemental_pat
- + = gen_rtx (SET, GET_MODE (SET_DEST (new_rtx_element->pat)),
- + SET_DEST (new_rtx_element->pat),
- + gen_rtx (PLUS, GET_MODE (XEXP (SET_SRC (new_rtx_element->pat), 0)),
- + SET_DEST (new_rtx_element->pat),
- + XEXP (XEXP (SET_SRC (new_rtx_element->pat), 1), 1)));
- + new_rtx_element->pat = PATTERN (new_rtx_element->insn);
- + }
- + else
- + {
- + return (0);
- + }
- + if (recog (new_rtx_element->supplemental_pat, insn, 0) < 0)
- + {
- + return (0);
- + }
- + }
- + return (1);
- + }
- +
- +
- + /* Generate a new rtx which is a copy of orig with each occurence of
- + biv_reg replaced by biv_reg+biv_adjust_const.
- + */
- + static rtx
- + make_new_use (orig, biv_reg, biv_adjust_const, insn)
- + register rtx orig, biv_reg;
- + rtx insn;
- + int biv_adjust_const;
- + {
- + register rtx copy;
- + rtx non_biv_operand, ret_rtx;
- + register int i, j;
- + register RTX_CODE code;
- + register char *format_ptr;
- +
- + code = GET_CODE (orig);
- +
- + switch (code)
- + {
- + case REG:
- + if (rtx_equal_p (orig, biv_reg))
- + {
- + ret_rtx
- + = gen_rtx (PLUS, GET_MODE (orig), orig,
- + gen_rtx (CONST_INT, 0, biv_adjust_const));
- + return (ret_rtx);
- + }
- + else
- + {
- + return (orig);
- + }
- + break;
- +
- + case PLUS:
- + case MINUS:
- + if (GET_CODE (XEXP (orig, 0)) == REG && GET_CODE (XEXP (orig, 1)) == CONST_INT
- + && rtx_equal_p (XEXP (orig, 0), biv_reg))
- + { /* Ajdust the const_int part by biv_adjust_const. */
- + if (GET_CODE (orig) == PLUS)
- + {
- + non_biv_operand
- + = gen_rtx (CONST_INT, 0,
- + INTVAL (XEXP (orig, 1)) + biv_adjust_const);
- + }
- + else
- + {
- + non_biv_operand
- + = gen_rtx (CONST_INT, 0,
- + INTVAL (XEXP (orig, 1)) - biv_adjust_const);
- + }
- + ret_rtx = gen_rtx (code, GET_MODE (orig), XEXP (orig, 0), non_biv_operand);
- + return (ret_rtx);
- + }
- + else
- + /* commutativity */
- + if (GET_CODE (XEXP (orig, 1)) == REG && GET_CODE (XEXP (orig, 0)) == CONST_INT
- + && rtx_equal_p (XEXP (orig, 1), biv_reg))
- + {/* Ajdust the const_int part by biv_adjust_const. */
- + if (GET_CODE (orig) == PLUS)
- + {
- + non_biv_operand
- + = gen_rtx (CONST_INT, 0,
- + INTVAL (XEXP (orig, 0)) + biv_adjust_const);
- + }
- + else
- + {
- + non_biv_operand
- + = gen_rtx (CONST_INT, 0,
- + INTVAL (XEXP (orig, 0)) - biv_adjust_const);
- + }
- + ret_rtx = gen_rtx (code, GET_MODE (orig), non_biv_operand, XEXP (orig, 1));
- + return (ret_rtx);
- + }
- + break;
- +
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + case PC:
- + case CC0:
- + return orig;
- + }
- +
- + copy = rtx_alloc (code);
- + PUT_MODE (copy, GET_MODE (orig));
- + copy->in_struct = orig->in_struct;
- + copy->volatil = orig->volatil;
- + copy->unchanging = orig->unchanging;
- + copy->integrated = orig->integrated;
- +
- + format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
- +
- + for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
- + {
- + switch (*format_ptr++)
- + {
- + case 'e':
- + XEXP (copy, i) = XEXP (orig, i);
- + if (XEXP (orig, i) != NULL)
- + XEXP (copy, i)
- + = make_new_use (XEXP (orig, i), biv_reg,
- + biv_adjust_const, insn);
- + break;
- +
- + case 'E':
- + case 'V':
- + XVEC (copy, i) = XVEC (orig, i);
- + if (XVEC (orig, i) != NULL)
- + {
- + XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
- + for (j = 0; j < XVECLEN (copy, i); j++)
- + XVECEXP (copy, i, j)
- + = make_new_use (XVECEXP (orig, i, j), biv_reg,
- + biv_adjust_const, insn);
- + }
- + break;
- +
- + default:
- + XINT (copy, i) = XINT (orig, i);
- + break;
- + }
- + }
- + return copy;
- + }
- +
- + /* Try to put orig into a form that is recognizable using rewrite_address
- + on the relevant portion of orig.
- + */
- + rtx
- + try_to_make_good (orig)
- + register rtx orig;
- + {
- + void rewrite_address ();
- + register int i, j;
- + register RTX_CODE code;
- + register char *fmt;
- +
- + code = GET_CODE (orig);
- +
- + switch (code)
- + {
- + case REG:
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + case PC:
- + case CC0:
- + return orig;
- +
- + case MEM:
- + GO_IF_LEGITIMATE_ADDRESS (GET_MODE (orig), orig, memok);
- + #ifdef REWRITE_ADDRESS
- + REWRITE_ADDRESS (orig);
- + #endif
- + memok:
- + return (orig);
- + }
- +
- +
- + fmt = GET_RTX_FORMAT (code);
- +
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + XEXP (orig, i) = try_to_make_good (XEXP (orig, i));
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (orig, i); j++)
- + XVECEXP (orig, i, j)
- + = try_to_make_good (XVECEXP (orig, i, j));
- + }
- + return orig;
- + }
- +
- +
- + /* Check to see if compare elimination is possible for this loop.
- + Return 1 if yes and set up *compare_insn to point to the compare
- + at the end of the loop and *jump_insn to point to the jump back
- + to the beginning of the loop.
- + */
- + static int
- + possible_compare_elimination (loop_start, loop_end, compare_insn, jump_insn, try_compare_elimination)
- + rtx loop_end, loop_start, *compare_insn, *jump_insn;
- + int *try_compare_elimination;
- + {
- + rtx insn;
- + int i;
- + insn = loop_start;
- + i = 0;
- + *try_compare_elimination = 0;
- + while (insn && insn != loop_end)
- + {
- + if (GET_CODE (insn) == CALL_INSN)
- + {
- + insn = NULL;
- + }
- + else if (GET_CODE (insn) == INSN)
- + {
- + i++;
- + if (i > MAX_CMP_ELIM)
- + {
- + insn = NULL;
- + }
- + else if (GET_CODE (PATTERN (insn)) != SET)
- + {
- + insn = NULL;
- + }
- + }
- + if (insn)
- + insn = NEXT_INSN (insn);
- + }
- + if (insn != NULL)
- + {
- + *try_compare_elimination = 1;
- + }
- + /* Look for compare jcc on this biv at the end of the loop. */
- + insn = PREV_INSN (loop_end);
- + if (!(GET_CODE (insn) == JUMP_INSN
- + && GET_CODE (PATTERN (insn)) == SET
- + && SET_DEST (PATTERN (insn)) == pc_rtx
- + && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE
- + && XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 1) == const0_rtx))
- + {
- + *try_compare_elimination = 0;
- + }
- + *jump_insn = insn;
- + insn = PREV_INSN (insn);
- + if (!(GET_CODE (insn) == INSN
- + && GET_CODE (PATTERN (insn)) == SET
- + && SET_DEST (PATTERN (insn)) == cc0_rtx
- + && GET_CODE (SET_SRC (PATTERN (insn))) == COMPARE
- + && (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT
- + || GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == REG)
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG))
- + {
- + *try_compare_elimination = 0;
- + }
- + *compare_insn = insn;
- + }
- +
- + struct regs_mentioned
- + {
- + rtx reg; /* The register. */
- + int in_mem; /* Is 1 if register is part of
- + a MEM_REF. */
- + struct regs_mentioned *next;
- + };
- +
- + static struct regs_mentioned *giv_reg_header = NULL, *use_reg_header = NULL;
- +
- + /* Build a linked list of (struct regs_mentioned) describing the
- + registers used in the pattern pat. The head of the linked list
- + to place them on is a_header. If in_mem is 1 this means that
- + pat is subexpression of a MEM_REF.
- + */
- + static void
- + find_regs_mentioned (pat, a_header, in_mem)
- + rtx pat;
- + struct regs_mentioned **a_header;
- + int in_mem;
- + {
- + register char *fmt;
- + register int i;
- + register enum rtx_code code;
- + struct regs_mentioned *one_reg;
- +
- + code = GET_CODE (pat);
- +
- + switch (code)
- + {
- + case REG:
- + if (REGNO (pat) < FIRST_PSEUDO_REGISTER)
- + {
- + return;
- + }
- + one_reg = (struct regs_mentioned *)
- + obstack_alloc (&momentary_obstack, sizeof (struct regs_mentioned));
- + one_reg->reg = pat;
- + one_reg->in_mem = in_mem;
- + one_reg->next = *a_header;
- + *a_header = one_reg;
- + return;
- +
- + /* These codes have no constituent expressions
- + and are unique. */
- + case SCRATCH:
- + case CC0:
- + case PC:
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + return;
- +
- + case MEM:
- + in_mem = 1;
- + break;
- +
- + }
- +
- +
- + fmt = GET_RTX_FORMAT (code);
- +
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + {
- + if (fmt[i] == 'E')
- + {
- + register int j;
- + for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
- + find_regs_mentioned (XVECEXP (pat, i, j), a_header, in_mem);
- + }
- + else if (fmt[i] == 'e')
- + find_regs_mentioned (XEXP (pat, i), a_header, in_mem);
- + }
- + }
- +
- + #ifdef REDUCE_INDEX
- + /* Create givs which are only index terms of memory addresses. */
- + static int
- + do_reduce_index (x, add_val)
- + rtx x, *add_val;
- + {
- + rtx mem_address, sym_part, constint_part, save_add_val;
- + save_add_val = *add_val;
- + mem_address = XEXP (x, 0);
- + if (GET_CODE (mem_address) != PLUS)
- + {
- + return (0);
- + }
- + if (GET_CODE (XEXP (mem_address, 0)) == MULT)
- + {
- + if (!LEGITIMATE_INDEX_P (XEXP (mem_address, 0))
- + || GET_CODE (XEXP (mem_address, 1)) == REG
- + )
- + { /* Will have index term anyway. */
- + return (0);
- + }
- + }
- + else
- + {
- + return (0);
- + }
- + /* Strip from *(add_val) the non index part. */
- + if (rtx_equal_p (*(add_val), XEXP (mem_address, 1)))
- + {
- + *(add_val) = const0_rtx;
- + }
- + else if (GET_CODE (*(add_val)) == CONST_INT)
- + {
- + if (GET_CODE (XEXP (mem_address, 1)) != CONST_INT)
- + {
- + return (0);
- + }
- + else
- + {
- + *(add_val)
- + = gen_rtx (CONST_INT, 0,
- + INTVAL (*(add_val)) - INTVAL (XEXP (mem_address, 1)));
- + }
- + }
- + else if (GET_CODE (*(add_val)) == CONST)
- + {
- + if (!(GET_CODE (XEXP (*(add_val), 0)) == PLUS
- + && GET_CODE (XEXP (XEXP (*(add_val), 0), 0)) == SYMBOL_REF
- + && GET_CODE (XEXP (XEXP (*(add_val), 0), 1)) == CONST_INT)
- + )
- + {
- + return (0);
- + }
- + *(add_val) = XEXP (*(add_val), 0);
- + mem_address = XEXP (mem_address, 1);
- + if (GET_CODE (mem_address) == CONST)
- + {
- + mem_address = XEXP (mem_address, 0);
- + }
- + if (GET_CODE (mem_address) == PLUS)
- + {
- + sym_part = XEXP (mem_address, 0);
- + constint_part = XEXP (mem_address, 1);
- + }
- + else
- + {
- + sym_part = mem_address;
- + constint_part = const0_rtx;
- + }
- + if (!rtx_equal_p (XEXP (*(add_val), 0), sym_part))
- + {
- + *(add_val) = save_add_val;
- + return (0);
- + }
- + else
- + {
- + *(add_val) = XEXP (*(add_val), 1);
- + *(add_val)
- + = gen_rtx (CONST_INT, 0, INTVAL (*(add_val)) - INTVAL (constint_part));
- + }
- + }
- + else
- + {
- + return (0);
- + }
- + return (1);
- + }
- +
- + #endif
- +
- + struct regopt_info
- + {
- + rtx insn_set; /* The insn that loads the current value in the register */
- + rtx corresp_mem; /* The memory that contains the same value as the register */
- + rtx reg; /* The register */
- + char replace_reg; /* If 1 replace reg with corresp_mem (for stack regs)
- + otherwise replace corresp_mem with reg */
- + char do_replace; /* If 1 then this is a stack reg that has already
- + been used in this extended basic block -
- + try to replace susequent uses with this regs
- + corresponding mem */
- + };
- + static struct regopt_info *rinfo;
- + struct undo
- + {
- + rtx *where;
- + rtx old_contents;
- + int is_int;
- + };
- +
- + #define MAX_UNDO 50
- +
- + struct undobuf
- + {
- + int num_undo;
- + char *storage;
- + struct undo undo[MAX_UNDO];
- + rtx other_insn;
- + };
- +
- + static struct undobuf undobuf;
- + #define LOOP_SUBST(WHERE, NEWVAL) \
- + do { if (undobuf.num_undo < MAX_UNDO) \
- + { \
- + undobuf.undo[undobuf.num_undo].where = WHERE; \
- + undobuf.undo[undobuf.num_undo].old_contents = *WHERE; \
- + undobuf.undo[undobuf.num_undo].is_int = 0; \
- + *WHERE = NEWVAL; \
- + undobuf.num_undo++; \
- + } \
- + } while (0)
- +
- +
- + static int mem_max_reg_num;
- + #define SYMREF_PLUS_REG(insn) \
- + (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS && \
- + GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG && \
- + GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == SYMBOL_REF)
- +
- + /* Try to replace a register use with the value that sets that the
- + register. This is done for the following cases:
- + 1) regx <- regy ashift const_int
- + 2) regx <- symbol_ref + regy
- + 3) regx <- (regy * const_int) + const_int
- +
- + If only_symref_plus_reg==1 then regx is replaced only if it
- + used as a base or index register and is of type 2)
- + otherwise it is always replaced.
- +
- + Calling use_regs_source with only_symref_plus_reg==0 on a loop
- + before strength reduction causes strength reduction to better handle
- + mem givs.
- +
- + Calling use_regs_source with only_symref_plus_reg==1 at the end of
- + loop optimization will do the replacement even if combine would not.
- +
- + also if only_symref_plus_reg==1 and if we have
- + 1) mem1 <- regx
- + then attempt to replace susequent uses of mem1 with regx
- +
- +
- + */
- +
- + static
- + void
- + use_regs_source (start, end, only_symref_plus_reg)
- + rtx start, end;
- + int only_symref_plus_reg;
- + {
- + rtx insn, src, new_src, dest, tinsn, tmp_rtx;
- + struct regs_mentioned *header, *a_reg_used;
- + int recog_ok, i, insn_code_num, nested;
- + char *storage1, *storage2;
- + int cur_max_reg = max_reg_num () + 1;
- + mem_max_reg_num = cur_max_reg;
- +
- + undobuf.num_undo = 0;
- + rinfo
- + = (struct regopt_info *) alloca (cur_max_reg * sizeof (struct regopt_info));
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- +
- + nested = 0;
- + insn = NEXT_INSN (start);
- + while (insn != end)
- + {
- + switch (GET_CODE (insn))
- + {
- +
- + case NOTE:
- + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
- + && only_symref_plus_reg)
- + {
- + nested++;
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
- + && only_symref_plus_reg)
- + {
- + nested--;
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + break;
- +
- + case JUMP_INSN:
- + if (nested == 0 || !only_symref_plus_reg)
- + {
- + if (SET_DEST (PATTERN (insn)) == pc_rtx
- + && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF)
- + {
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + else if (!only_symref_plus_reg)
- + {
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + rinfo[i].corresp_mem = NULL;
- + }
- + }
- + }
- + break;
- +
- + case CALL_INSN:
- + if (nested == 0 || !only_symref_plus_reg)
- + {
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + break;
- +
- + case CODE_LABEL:
- + case BARRIER:
- + if (nested == 0 || !only_symref_plus_reg)
- + {
- + /* Forget everything */
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + break;
- +
- + case INSN:
- + if (!(nested == 0 || !only_symref_plus_reg))
- + break;
- + if (GET_CODE (PATTERN (insn)) == CLOBBER)
- + {
- + dest = SET_DEST (PATTERN (insn));
- + if (GET_CODE (dest) == REG)
- + {
- + rinfo[ REGNO (dest)].insn_set = NULL;
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && reg_overlap_mentioned_p (dest,
- + SET_SRC (PATTERN (rinfo[i].insn_set)))
- + )
- + { /* current value of reg dest overwritten */
- + rinfo[i].insn_set = NULL;
- + if (rinfo[i].corresp_mem
- + && reg_overlap_mentioned_p (dest,
- + rinfo[i].corresp_mem))
- + { /* Not the same memory address anymore. */
- + rinfo[i].corresp_mem = NULL;
- + }
- + }
- + }
- + }
- + else if (GET_CODE (dest) == MEM && !only_symref_plus_reg
- + && flag_replace_mem)
- + {
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].corresp_mem
- + && true_dependence (dest, rinfo[i].corresp_mem))
- + { /* Memory address maybe overwritten. */
- + rinfo[i].corresp_mem = NULL;
- + }
- + }
- + }
- + } else if (GET_CODE (PATTERN (insn)) == PARALLEL)
- + {
- + dest = SET_DEST (PATTERN (insn));
- + for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- + {
- + rtx cur_rtx;
- + cur_rtx = XVECEXP (PATTERN (insn), 0, i);
- + if ((GET_CODE (cur_rtx) == SET || GET_CODE (cur_rtx) == CLOBBER)
- + && GET_CODE (SET_DEST (cur_rtx)) == REG)
- + {
- + rinfo[ REGNO (SET_DEST (cur_rtx))].insn_set = NULL;
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && reg_overlap_mentioned_p (SET_DEST (cur_rtx),
- + SET_SRC (PATTERN (rinfo[i].insn_set)))
- + )
- + { /* Current value of reg dest overwritten */
- + rinfo[i].insn_set = NULL;
- + }
- + if (rinfo[i].corresp_mem
- + && reg_overlap_mentioned_p (SET_DEST (cur_rtx),
- + rinfo[i].corresp_mem))
- + { /* Not the same memory address anymore. */
- + rinfo[i].corresp_mem = NULL;
- + }
- + }
- + }
- + else if ((GET_CODE (cur_rtx) == SET || GET_CODE (cur_rtx) == CLOBBER)
- + && GET_CODE (SET_DEST (cur_rtx)) == MEM
- + && GET_CODE (dest) == MEM && !only_symref_plus_reg
- + && flag_replace_mem)
- + {
- + dest = SET_DEST (cur_rtx);
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].corresp_mem
- + && true_dependence (dest, rinfo[i].corresp_mem))
- + { /* Memory address maybe overwritten. */
- + rinfo[i].corresp_mem = NULL;
- + }
- + }
- + }
- + else if (!(GET_CODE (cur_rtx) == SET
- + || GET_CODE (cur_rtx) == CLOBBER
- + || GET_CODE (cur_rtx) == USE))
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + }
- + else if (GET_CODE (PATTERN (insn)) == SET)
- + {
- + dest = SET_DEST (PATTERN (insn));
- + if (GET_CODE (SET_SRC (PATTERN (insn))) != REG)
- + {
- + header = NULL;
- + storage2 = (char *) obstack_alloc (&momentary_obstack, 0);
- + find_regs_mentioned (SET_SRC (PATTERN (insn)), &header, 0);
- + a_reg_used = header;
- + while (a_reg_used)
- + {
- + undobuf.num_undo = 0;
- + undobuf.storage = (char *) oballoc (0);
- + if (((a_reg_used->in_mem || !only_symref_plus_reg)
- + && rinfo[REGNO (a_reg_used->reg)].insn_set
- + && rinfo[REGNO (a_reg_used->reg)].replace_reg == 0
- + && (!only_symref_plus_reg
- + || SYMREF_PLUS_REG (rinfo[REGNO (a_reg_used->reg)].insn_set)))
- + || (rinfo[REGNO (a_reg_used->reg)].corresp_mem
- + && rinfo[REGNO (a_reg_used->reg)].insn_set
- + && rinfo[REGNO (a_reg_used->reg)].replace_reg == 1
- + && rinfo[REGNO (a_reg_used->reg)].do_replace == 1
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + && !((GET_CODE (SET_SRC (PATTERN (insn))) == FLOAT_EXTEND
- + || GET_CODE (SET_SRC (PATTERN (insn))) == FLOAT_TRUNCATE)
- + && (IS_STACK_MODE (SFmode) || IS_STACK_MODE (DFmode)))
- +
- + #endif
- + #endif
- + && !only_symref_plus_reg && flag_replace_stack_mem)
- + )
- + { /* Try to replace the register with it's current
- + value. */
- + replace_reg (SET_SRC (PATTERN (insn)),
- + &SET_SRC (PATTERN (insn)),
- + a_reg_used->reg,
- + &(rinfo[REGNO (a_reg_used->reg)]));
- + if ((insn_code_num = recog (PATTERN (insn), insn, 0)) < 0)
- + {
- + recog_ok = 0;
- + try_to_make_good (SET_SRC (PATTERN (insn)));
- + }
- + else
- + {
- + recog_ok = 1;
- + }
- + if (recog_ok
- + || (insn_code_num = recog (PATTERN (insn), insn, 0)) >= 0)
- + {
- + INSN_CODE (insn) = insn_code_num;
- + /* canonicalize */
- + if (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == MULT
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG)
- + {
- + tmp_rtx = XEXP (SET_SRC (PATTERN (insn)), 0);
- + XEXP (SET_SRC (PATTERN (insn)), 0)
- + = XEXP (SET_SRC (PATTERN (insn)), 1);
- + XEXP (SET_SRC (PATTERN (insn)), 1) = tmp_rtx;
- + }
- + }
- + else
- + {
- + loop_undo_all ();
- + }
- + }
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + if (IS_STACK_MODE (GET_MODE (a_reg_used->reg)))
- + {
- + rinfo[REGNO (a_reg_used->reg)].do_replace = 1;
- + }
- + #endif
- + #endif
- + a_reg_used = a_reg_used->next;
- + }
- + if (header != NULL)
- + {
- + obstack_free (&momentary_obstack, storage2);
- + }
- + if (!only_symref_plus_reg && flag_replace_mem)
- + replace_mems (insn, SET_SRC (PATTERN (insn)));
- + }
- + src = SET_SRC (PATTERN (insn));
- + if (GET_CODE (dest) != REG)
- + {
- + header = NULL;
- + storage2 = (char *) obstack_alloc (&momentary_obstack, 0);
- + find_regs_mentioned (SET_DEST (PATTERN (insn)), &header, 0);
- + a_reg_used = header;
- + while (a_reg_used)
- + {
- + undobuf.num_undo = 0;
- + undobuf.storage = (char *) oballoc (0);
- + if (a_reg_used->in_mem
- + && rinfo[REGNO (a_reg_used->reg)].insn_set
- + && (!only_symref_plus_reg
- + || SYMREF_PLUS_REG (rinfo[REGNO (a_reg_used->reg)].insn_set))
- + )
- + { /* Try to replace the register with it's current
- + value. */
- + replace_reg (SET_DEST (PATTERN (insn)),
- + &SET_DEST (PATTERN (insn)),
- + a_reg_used->reg,
- + &(rinfo[REGNO (a_reg_used->reg)]));
- +
- + if (recog (PATTERN (insn), insn, 0) < 0)
- + {
- + recog_ok = 0;
- + try_to_make_good (SET_DEST (PATTERN (insn)));
- + }
- + else
- + {
- + recog_ok = 1;
- + }
- + if (recog_ok
- + || recog (PATTERN (insn), insn, 0) >= 0)
- + {
- + ;
- + }
- + else
- + {
- + loop_undo_all ();
- + }
- + }
- + a_reg_used = a_reg_used->next;
- + }
- + if (header != NULL)
- + {
- + obstack_free (&momentary_obstack, storage2);
- + }
- + if (!only_symref_plus_reg
- + && GET_CODE (src) == REG && GET_CODE (dest) == MEM
- + && !MEM_VOLATILE_P (dest)
- + && GET_CODE (XEXP (dest, 0)) != PRE_DEC
- + && GET_CODE (XEXP (dest, 0)) != PRE_INC
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + && !(IS_STACK_MODE (GET_MODE (src)))
- + #endif
- + #endif
- + )
- + {
- + rinfo[REGNO (src)].corresp_mem = dest;
- + rinfo[REGNO (src)].reg = src;
- + rinfo[REGNO (src)].replace_reg = 0;
- + }
- + }
- + if (GET_CODE (dest) == MEM && !only_symref_plus_reg
- + && flag_replace_mem)
- + {
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].corresp_mem && !(GET_CODE (src) == REG && i == REGNO (src))
- + && true_dependence (dest, rinfo[i].corresp_mem))
- + { /* Memory address maybe overwritten. */
- + rinfo[i].corresp_mem = NULL;
- + }
- + }
- + }
- + if (GET_CODE (dest) == REG)
- + {
- + for (i = 0; i < cur_max_reg; i++)
- + {
- + if (rinfo[i].insn_set
- + && reg_overlap_mentioned_p (dest, SET_SRC (PATTERN (rinfo[i].insn_set)))
- + )
- + { /* Current value of reg dest overwritten. */
- + rinfo[i].insn_set = NULL;
- + }
- + if (rinfo[i].corresp_mem
- + && reg_overlap_mentioned_p (dest, rinfo[i].corresp_mem))
- + { /* Not the same memory address anymore. */
- + rinfo[i].corresp_mem = NULL;
- + }
- + }
- + rinfo[REGNO (dest)].corresp_mem = NULL;
- + if (reg_overlap_mentioned_p (dest, SET_SRC (PATTERN (insn))))
- + {
- + rinfo[REGNO (dest)].insn_set = NULL;
- + }
- + else
- + {
- + if ((GET_CODE (SET_SRC (PATTERN (insn))) == ASHIFT
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
- + || (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == SYMBOL_REF)
- + || (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == MULT
- + && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0)) == REG
- + && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 1)) == CONST_INT
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
- + )
- + { /* These are the patterns of interest. */
- + rinfo[REGNO (dest)].insn_set = insn;
- + }
- + else
- + {
- + rinfo[REGNO (dest)].insn_set = NULL;
- + }
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + if (IS_STACK_MODE (GET_MODE (dest))
- + && ((GET_CODE (src) == MEM
- + && !MEM_VOLATILE_P (src))
- + || ((IS_STACK_MODE (SFmode) || IS_STACK_MODE (DFmode))
- + && (GET_CODE (src) == FLOAT_EXTEND
- + || GET_CODE (src) == FLOAT_TRUNCATE)
- + && GET_CODE (XEXP (src, 0)) == MEM
- + && !MEM_VOLATILE_P (XEXP (src, 0))))
- + && flag_replace_stack_mem)
- + {
- + rinfo[REGNO (dest)].corresp_mem = src;
- + rinfo[REGNO (dest)].reg = dest;
- + rinfo[REGNO (dest)].insn_set = insn;
- + rinfo[REGNO (dest)].replace_reg = 1;
- + rinfo[REGNO (dest)].do_replace = 0;
- + }
- + #endif
- + #endif
- + }
- + }
- + }
- + else if (GET_CODE (PATTERN (insn)) != USE)
- + {
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + }
- + break;
- +
- + default:
- + bzero (rinfo, cur_max_reg * sizeof (struct regopt_info));
- + break;
- + }
- + insn = NEXT_INSN (insn);
- + }
- + }
- +
- + void
- + loop_undo_all ()
- + {
- + register int i;
- + if (undobuf.num_undo > MAX_UNDO)
- + undobuf.num_undo = MAX_UNDO;
- + for (i = undobuf.num_undo - 1; i >= 0; i--)
- + *undobuf.undo[i].where = undobuf.undo[i].old_contents;
- +
- + obfree (undobuf.storage);
- + undobuf.num_undo = 0;
- + }
- +
- + /* Replace in pat of insn each MEM with a corresponding reg if one exists. */
- + static
- + rtx
- + replace_mems (insn, pat)
- + rtx insn, pat;
- + {
- + register RTX_CODE code = GET_CODE (pat);
- + register int i, j;
- + register char *fmt;
- +
- + switch (code)
- + {
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + case REG:
- + return pat;
- +
- +
- + }
- +
- + if (GET_CODE (pat) == MEM)
- + {
- + for (i = 0; i < mem_max_reg_num; i++)
- + {
- + if (rinfo[i].corresp_mem && rinfo[i].replace_reg == 0
- + && rtx_equal_p (rinfo[i].corresp_mem, pat))
- + {
- + return (rinfo[i].reg);
- + }
- + }
- + }
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + XEXP (pat, i) = replace_mems (insn, XEXP (pat, i));
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + XVECEXP (pat, i, j)
- + = replace_mems (insn, XVECEXP (pat, i, j));
- + }
- + return pat;
- + }
- +
- +
- + /* Replace in orig each occurrence of reg_rplc with the value
- + described by *rptr. The location in orig of reg_rplc is where.
- + */
- + static void
- + replace_reg (orig, where, reg_rplc, rptr)
- + register rtx orig, reg_rplc;
- + rtx *where;
- + struct regopt_info *rptr;
- + {
- + rtx non_biv_operand, ret_rtx;
- + register int i, j;
- + register RTX_CODE code;
- + register char *fmt;
- +
- + code = GET_CODE (orig);
- +
- + switch (code)
- + {
- + case REG:
- + if (rtx_equal_p (orig, reg_rplc))
- + {
- + if (GET_CODE (SET_SRC (PATTERN (rptr->insn_set))) == ASHIFT
- + && GET_CODE (XEXP (SET_SRC (PATTERN (rptr->insn_set)), 1)) == CONST_INT
- + )
- + {
- + LOOP_SUBST (where,
- + (gen_rtx (MULT, GET_MODE (SET_SRC (PATTERN (rptr->insn_set))),
- + XEXP (SET_SRC (PATTERN (rptr->insn_set)), 0),
- + gen_rtx (CONST_INT, 0,
- + two_to_power (INTVAL (XEXP (SET_SRC (PATTERN (rptr->insn_set)), 1)))))));
- + }
- + else
- + {
- + LOOP_SUBST (where, (SET_SRC (PATTERN (rptr->insn_set))));
- + }
- + }
- + break;
- +
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + case PC:
- + case CC0:
- + return;
- + }
- +
- +
- + fmt = GET_RTX_FORMAT (code);
- +
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + replace_reg (XEXP (orig, i), &XEXP (orig, i), reg_rplc, rptr);
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (orig, i); j++)
- + replace_reg (XVECEXP (orig, i, j), &XVECEXP (orig, i, j), reg_rplc, rptr);
- + }
- + }
- +
- +
- + static int
- + two_to_power (x)
- + int x;
- + {
- + int retval, i;
- +
- + retval = 1;
- + for (i = 0; i < x; i++)
- + retval *= 2;
- + return (retval);
- + }
- +
- +
- + /* Return 1 iff insn p jumps backward to a label that is located
- + between loop_start and p,
- + if strict==1 we also require that any jumps between the target label and
- + p jump to labels that are between the target label and p. */
- + static int
- + jumps_back_in_loop (p, loop_start, use1, strict)
- + rtx p, loop_start;
- + int use1; /* If 1 then we require each label within to be accessed only once */
- + int strict;
- + {
- + rtx insn, target, last_jump_found;
- + int jumps_found, labels_found;
- +
- + if (!flag_jump_back)
- + return (0);
- + target = JUMP_LABEL (p);
- + insn = PREV_INSN (p);
- + jumps_found = 0;
- + labels_found = 0;
- + while (insn != target && insn != loop_start)
- + {
- + if (GET_CODE (insn) == JUMP_INSN)
- + {
- + jumps_found++;
- + }
- + else if (GET_CODE (insn) == CODE_LABEL)
- + {
- + if (use1 && LABEL_NUSES (insn) != 1)
- + {
- + return (0);
- + }
- + labels_found++;
- + }
- +
- + insn = PREV_INSN (insn);
- + }
- + if (insn != target)
- + {
- + return (0);
- + }
- + else
- + {
- + if (use1 && jumps_found != labels_found)
- + {
- + return (0);
- + }
- + if (jumps_found == 0 || strict == 0)
- + {
- + return (1);
- + }
- + else
- + { /* Must check each jump to see that it jumps to label
- + between target and p. */
- + last_jump_found = target;
- + while (jumps_found)
- + {
- + /* Find the next jump. */
- + insn = NEXT_INSN (last_jump_found);
- + while (GET_CODE (insn) != JUMP_INSN)
- + {
- + insn = NEXT_INSN (insn);
- + }
- + last_jump_found = insn;
- + /* Now find the target. */
- + while (insn != p && insn != JUMP_LABEL (last_jump_found))
- + { /* Search forward. */
- + insn = NEXT_INSN (insn);
- + }
- + if (insn == JUMP_LABEL (last_jump_found)
- + && (!use1 || LABEL_NUSES (JUMP_LABEL (last_jump_found)) == 1)
- + )
- + {
- + jumps_found--;
- + }
- + else
- + {
- + while (insn != loop_start && insn != JUMP_LABEL (last_jump_found))
- + { /* Search backwards. */
- + insn = PREV_INSN (insn);
- + }
- + if (insn == JUMP_LABEL (last_jump_found)
- + && (!use1 || LABEL_NUSES (JUMP_LABEL (last_jump_found)) == 1)
- + )
- + {
- + jumps_found--;
- + }
- + else
- + {
- + break;
- + }
- + }
- + }
- + return (jumps_found == 0);
- + }
- + }
- + }
- +
- +
- + struct propogate_cand
- + {
- + rtx srcpat;
- + rtx add_reg0;
- + rtx add_reg1;
- + rtx mul_reg;
- + rtx reg;
- + int mul_val;
- + char cand_type;
- + };
- +
- + struct unroll_combine_cand
- + {
- + rtx reg;
- + struct unroll_combine_cand *next;
- + };
- +
- + #define COPY 1
- + #define GIV 2
- +
- + /* Try to propogate copies into loop as follows:
- + If before the loop we have
- + regx <- regy
- + and in the loop regx is only used, then replace each use of regx
- + in the loop with regy
- + */
- + static
- + loop_copy_propogate (loop_start, loop_end)
- + rtx loop_start, loop_end;
- + {
- + struct propogate_cand *copy_candidates, *possible_giv_candidate;
- + char *regs_set, dummyc;
- + rtx insn, loop_label, loop_jump, dest, src, *split_giv_src;
- + int num_copy_candidates, num_giv_candidates,
- + stop_looking, cur_max_regnum, i, dummyi, num_unroll_candidates;
- + struct unroll_combine_cand **unroll_cands, *an_unroll_cand;
- +
- + cur_max_regnum = max_reg_num () + 1;
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "copy prop from %d to %d\n",
- + INSN_UID (loop_start), INSN_UID (loop_end));
- + }
- + copy_candidates = (struct propogate_cand *)
- + alloca (cur_max_regnum * sizeof (struct propogate_cand));
- + bzero (copy_candidates, (cur_max_regnum * sizeof (struct propogate_cand)));
- + regs_set = (char *) alloca (cur_max_regnum);
- + bzero (regs_set, cur_max_regnum);
- + n_times_set = (short *) alloca (cur_max_regnum * sizeof (short));
- + bzero (n_times_set, cur_max_regnum * sizeof (short));
- + may_not_optimize = (char *) alloca (cur_max_regnum); /* not used */
- + if (flag_unroll_loops)
- + {
- + unroll_cands
- + = (struct unroll_combine_cand **)
- + alloca (cur_max_regnum * sizeof (struct unroll_combine_cand *));
- + bzero (unroll_cands, cur_max_regnum * sizeof (struct unroll_combine_cand *));
- + split_giv_src = (rtx *) alloca (cur_max_regnum * sizeof (rtx));
- + bzero (split_giv_src, cur_max_regnum * sizeof (rtx));
- + }
- + /* First check that the label that is the start of the loop
- + is only jumped to from within the loop - if not return
- + */
- + insn = loop_start;
- + while (insn && GET_CODE (insn) != CODE_LABEL)
- + {
- + insn = NEXT_INSN (insn);
- + }
- + loop_label = insn;
- + insn = loop_end;
- + while (insn && GET_CODE (insn) != JUMP_INSN)
- + {
- + insn = PREV_INSN (insn);
- + }
- + loop_jump = insn;
- + if (!loop_label || !loop_jump
- + || (JUMP_LABEL (loop_jump) != loop_label)
- + || (LABEL_NUSES (JUMP_LABEL (loop_jump)) != 1)
- + )
- + {
- + return;
- + }
- + /* Compute n_times_set */
- + count_loop_regs_set (loop_start, loop_end, may_not_optimize, NULL,
- + &dummyi, cur_max_regnum);
- +
- + /* Look backwards from loop_start until a label barier or
- + uncoditional jump is reached,
- + searching for insns of the form regx <- regy and regx
- + NOT set in loop - these are candidates for copy propogation.
- + Also search for registers that are set rega <- regb*C + regd
- + - rega is a candidate for inter loop giv combination.
- + */
- + insn = loop_start;
- + num_copy_candidates = 0;
- + num_giv_candidates = 0;
- + num_unroll_candidates = 0;
- + stop_looking = 0;
- + possible_giv_candidate = NULL;
- + while (insn && !stop_looking)
- + {
- + switch (GET_CODE (insn))
- + {
- + case NOTE:
- + break;
- +
- + case JUMP_INSN:
- + if (SET_DEST (PATTERN (insn)) == pc_rtx
- + && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF)
- + {
- + stop_looking = 1;
- + }
- + break;
- +
- + case CODE_LABEL:
- + case BARRIER:
- + stop_looking = 1;
- + break;
- +
- + case INSN:
- + if (GET_CODE (PATTERN (insn)) != SET)
- + {
- + stop_looking = 1;
- + }
- + else
- + {
- + dest = SET_DEST (PATTERN (insn));
- + src = SET_SRC (PATTERN (insn));
- + if (GET_CODE (dest) == REG)
- + {
- + if (flag_unroll_loops && dest != cc0_rtx
- + && REGNO (dest) >= FIRST_PSEUDO_REGISTER
- + && dest != pc_rtx && regs_set[REGNO (dest)] == 0
- + && GET_CODE (src) == REG && regs_set[REGNO (src)] == 0
- + && REGNO (src) >= FIRST_PSEUDO_REGISTER )
- + { /* The dest may be a split giv which we want
- + to combine */
- + if (split_giv_src[REGNO (dest)] == NULL)
- + {
- + split_giv_src[REGNO (dest)] = src;
- + an_unroll_cand
- + = (struct unroll_combine_cand *)
- + alloca (sizeof (struct unroll_combine_cand));
- + an_unroll_cand->reg = dest;
- + an_unroll_cand->next = unroll_cands[REGNO (src)];
- + unroll_cands[REGNO (src)] = an_unroll_cand;
- + num_unroll_candidates++;
- + }
- + else
- + {
- + split_giv_src[REGNO (dest)] = (rtx) - 1;
- + }
- + }
- +
- + if (dest != cc0_rtx && dest != pc_rtx
- + && REGNO (dest) >= FIRST_PSEUDO_REGISTER
- + && regs_set[REGNO (dest)] == 0)
- + {
- + if (GET_CODE (src) == REG
- + && REGNO (src) >= FIRST_PSEUDO_REGISTER
- + && n_times_set[REGNO (src)] == 0
- + && regs_set[REGNO (src)] == 0)
- + {
- + if (n_times_set[REGNO (dest)] == 0)
- + {
- + num_copy_candidates++;
- + copy_candidates[REGNO (dest)].srcpat = src;
- + copy_candidates[REGNO (dest)].cand_type = COPY;
- + }
- + }
- + else
- + {
- + if (GET_CODE (src) == PLUS
- + && GET_CODE (XEXP (src, 0)) == REG
- + && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER
- + && GET_CODE (XEXP (src, 1)) == REG
- + && REGNO (XEXP (src, 1)) >= FIRST_PSEUDO_REGISTER
- + && regs_set[REGNO (XEXP (src, 0))] == 0
- + && regs_set[REGNO (XEXP (src, 1))] == 0
- + && n_times_set[REGNO (XEXP (src, 1))] == 0
- + && copy_candidates[REGNO (dest)].srcpat == NULL
- + && copy_candidates[REGNO (dest)].add_reg0 == NULL)
- + {
- + copy_candidates[REGNO (dest)].add_reg0
- + = XEXP (src, 0);
- + copy_candidates[REGNO (dest)].add_reg1
- + = XEXP (src, 1);
- + possible_giv_candidate
- + = ©_candidates[REGNO (dest)];
- + possible_giv_candidate->reg = dest;
- + }
- + else if (GET_CODE (src) == ASHIFT
- + && GET_CODE (XEXP (src, 0)) == REG
- + && GET_CODE (XEXP (src, 1)) == CONST_INT
- + && regs_set[REGNO (XEXP (src, 0))] == 0
- + && possible_giv_candidate
- + && possible_giv_candidate->mul_reg == NULL
- + && rtx_equal_p (dest, possible_giv_candidate->add_reg0)
- + )
- + {
- + possible_giv_candidate->mul_reg = XEXP (src, 0);
- + possible_giv_candidate->mul_val
- + = two_to_power (INTVAL (XEXP (src, 1)));
- + possible_giv_candidate->cand_type = GIV;
- + num_giv_candidates++;
- + }
- + }
- + }
- + regs_set[REGNO (dest)] = 1;
- + }
- + }
- + break;
- +
- + default:
- + stop_looking = 1;
- + break;
- + }
- + insn = PREV_INSN (insn);
- + }
- + if (num_copy_candidates != 0)
- + {
- + /* Now for each candidate do the replacement */
- + do_replace (loop_start, loop_end, copy_candidates);
- + }
- + if (num_unroll_candidates != 0)
- + {
- + try_unroll_propogation (loop_start, loop_end, unroll_cands, split_giv_src);
- + }
- + }
- +
- + /*
- + Each occurence of a copy_candidate in an insn between loop_start
- + and loop_end is replaced by the corresponding register.
- + */
- + static
- + do_replace (loop_start, loop_end, copy_candidates)
- + rtx loop_start, loop_end;
- + struct propogate_cand *copy_candidates;
- + {
- + rtx insn, subst_cands ();
- +
- + for (insn = loop_start; insn != loop_end; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + subst_cands (insn, PATTERN (insn), copy_candidates);
- + }
- + }
- + }
- +
- +
- + /* Each register in pat which is a copy_candidate of type COPY is replaced with
- + it's copy from outside the loop.
- + */
- + static
- + rtx
- + subst_cands (insn, pat, copy_candidates)
- + rtx insn, pat;
- + struct propogate_cand *copy_candidates;
- + {
- + register RTX_CODE code = GET_CODE (pat);
- + register int i, j;
- + register char *fmt;
- +
- + switch (code)
- + {
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + return pat;
- +
- + case REG:
- + {
- + register int regno = REGNO (pat);
- +
- + if (copy_candidates[regno].srcpat
- + && copy_candidates[regno].cand_type == COPY)
- + {
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "replacing reg%d with reg%d in insn %d\n",
- + regno, REGNO (copy_candidates[regno].srcpat), INSN_UID (insn));
- + }
- + return (copy_candidates[regno].srcpat);
- + }
- + }
- + return pat;
- +
- + }
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + XEXP (pat, i) = subst_cands (insn, XEXP (pat, i), copy_candidates);
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + XVECEXP (pat, i, j)
- + = subst_cands (insn, XVECEXP (pat, i, j), copy_candidates);
- + }
- + return pat;
- + }
- +
- + struct reg_incs
- + {
- + int inc_val;
- + char invalid;
- + };
- +
- + /* Try to combine split givs from unrolling into one giv to decrease
- + register pressure and increase scheduling possiblities
- + */
- + static
- + try_unroll_propogation (loop_start, loop_end, unroll_cands, split_giv_src)
- + rtx loop_start, loop_end;
- + struct unroll_combine_cand **unroll_cands;
- + rtx *split_giv_src;
- + {
- + rtx insn, src, dest, ninsn, nsrc, ndest, unroll_subst_cands ();
- + struct reg_incs *reg_inc;
- + int i, cur_max_regnum, found;
- +
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " unroll propogate from %d to %d\n",
- + INSN_UID (loop_start), INSN_UID (loop_end));
- + }
- + cur_max_regnum = max_reg_num () + 1;
- + reg_inc
- + = (struct reg_incs *) alloca (cur_max_regnum * (sizeof (struct reg_incs)));
- + bzero (reg_inc, cur_max_regnum * (sizeof (struct reg_incs)));
- + insn = NEXT_INSN (loop_start);
- + while (insn != loop_end)
- + {
- + switch (GET_CODE (insn))
- + {
- +
- + case NOTE:
- + break;
- +
- + case JUMP_INSN:
- + case CODE_LABEL:
- + case BARRIER:
- + unroll_consistancy_maintained (cur_max_regnum, unroll_cands,
- + reg_inc, insn, split_giv_src);
- + /* forget everything */
- + bzero (reg_inc, cur_max_regnum * (sizeof (struct reg_incs)));
- + break;
- +
- + case INSN:
- + if (GET_CODE (PATTERN (insn)) == PARALLEL)
- + {
- + return;
- + }
- + if (GET_CODE (PATTERN (insn)) != SET)
- + {
- + return;
- + }
- + dest = SET_DEST (PATTERN (insn));
- + if (GET_CODE (dest) == REG)
- + {
- + if (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
- + && rtx_equal_p (XEXP (SET_SRC (PATTERN (insn)), 0), dest)
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
- + { /* reg incremented by constatnt */
- + reg_inc[REGNO (dest)].inc_val
- + += INTVAL (XEXP (SET_SRC (PATTERN (insn)), 1));
- + }
- + else
- + {
- + reg_inc[REGNO (dest)].invalid = 1;
- + }
- + }
- + break;
- +
- + default:
- + return;
- + break;
- + }
- + insn = NEXT_INSN (insn);
- + }
- + insn = NEXT_INSN (loop_start);
- + /* Combine each valid unroll candidate */
- + for (insn = loop_start; insn != loop_end; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + unroll_subst_cands (insn, PATTERN (insn), unroll_cands, split_giv_src);
- + }
- + }
- + }
- +
- +
- + /* Try to combine split givs from unrolling into one giv to decrease
- + register pressure and increase scheduling possiblities
- + */
- + static
- + rtx
- + unroll_subst_cands (insn, pat, unroll_cands, split_giv_src)
- + rtx insn, pat;
- + struct unroll_combine_cand **unroll_cands;
- + rtx *split_giv_src;
- + {
- + register RTX_CODE code = GET_CODE (pat);
- + register int i, j;
- + register char *fmt;
- +
- + if (GET_CODE (pat) == REG && pat == SET_DEST (PATTERN (insn)))
- + {
- + return (pat);
- + }
- + switch (code)
- + {
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + return pat;
- +
- + case REG:
- + {
- + register int regno = REGNO (pat);
- +
- + if (split_giv_src[regno] && split_giv_src[regno] != (rtx) - 1
- + && unroll_cands[REGNO (split_giv_src[regno])])
- + {
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " replacing reg%d with reg%d in insn %d\n",
- + regno, REGNO (split_giv_src[regno]), INSN_UID (insn));
- + }
- + return (split_giv_src[regno]);
- + }
- + }
- + return pat;
- +
- + }
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + XEXP (pat, i)
- + = unroll_subst_cands (insn, XEXP (pat, i), unroll_cands, split_giv_src);
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + XVECEXP (pat, i, j)
- + = unroll_subst_cands (insn, XVECEXP (pat, i, j), unroll_cands,
- + split_giv_src);
- + }
- + return pat;
- + }
- +
- + /* Check that spilt givs remain consistant */
- + static
- + unroll_consistancy_maintained (cur_max_regnum, unroll_cands, reg_inc, insn,
- + split_giv_src)
- + int cur_max_regnum;
- + struct unroll_combine_cand **unroll_cands;
- + struct reg_incs *reg_inc;
- + rtx *split_giv_src;
- + rtx insn;
- + {
- + int i;
- + struct unroll_combine_cand *an_unroll_cand;
- +
- + for (i = 0; i < cur_max_regnum; i++)
- + {
- + if (unroll_cands[i])
- + {
- + if (reg_inc[i].invalid)
- + {
- + unroll_cands[i] = NULL;
- + }
- + else
- + { /* Check each candidate to see that it was incremented
- + by same amount. */
- + an_unroll_cand = unroll_cands[i];
- + while (an_unroll_cand)
- + {
- + if (reg_inc[REGNO (an_unroll_cand->reg)].invalid
- + || reg_inc[REGNO (an_unroll_cand->reg)].inc_val !=
- + reg_inc[i].inc_val)
- + {
- + split_giv_src[REGNO (an_unroll_cand->reg)] = (rtx) - 1;
- + }
- + an_unroll_cand = an_unroll_cand->next;
- + }
- + }
- + }
- + }
- + }
- +
- +
- + #ifdef STORE_NOT_SET_CC0
- + #ifdef STACK_REGS
- + /* do_spl is called after reload because the reloader decides to spill
- + fp regs, for no appareant reason, if it is done before.
- + */
- + void
- + do_spl (f)
- + /* f is the first instruction of a chain of insns for one function */
- + rtx f;
- + {
- + register rtx insn;
- + register int i;
- + rtx end;
- + rtx last_insn;
- +
- + #ifndef HAVE_cc0
- + return;
- + #endif
- +
- + /* Count the number of loops. */
- +
- + max_loop_num = 0;
- + for (insn = f; insn; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == NOTE
- + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- + max_loop_num++;
- + }
- +
- + /* Don't waste time if no loops. */
- + if (max_loop_num == 0)
- + return;
- + doing_spl = 1;
- + /* Get size to use for tables indexed by uids.
- + Leave some space for labels allocated by find_and_verify_loops. */
- + max_uid_for_loop = get_max_uid () + 1 + max_loop_num * 4;
- +
- + uid_luid = (int *) alloca (max_uid_for_loop * sizeof (int));
- + uid_loop_num = (int *) alloca (max_uid_for_loop * sizeof (int));
- +
- + bzero (uid_luid, max_uid_for_loop * sizeof (int));
- + bzero (uid_loop_num, max_uid_for_loop * sizeof (int));
- +
- + /* Allocate tables for recording each loop. We set each entry, so they need
- + not be zeroed. */
- + loop_number_loop_starts = (rtx *) alloca (max_loop_num * sizeof (rtx));
- + loop_number_loop_ends = (rtx *) alloca (max_loop_num * sizeof (rtx));
- + loop_outer_loop = (int *) alloca (max_loop_num * sizeof (int));
- + loop_invalid = (char *) alloca (max_loop_num * sizeof (char));
- + loop_number_exit_labels = (rtx *) alloca (max_loop_num * sizeof (rtx));
- +
- + /* Find and spl each loop.
- + First, find them, and record them in order of their beginnings. */
- + find_and_verify_loops (f);
- + for (i = max_loop_num - 1; i >= 0; i--)
- + {
- + if (loop_number_loop_ends[i])
- + loop_spl (loop_number_loop_starts[i], loop_number_loop_ends[i], i, 1);
- + }
- + doing_spl = 0;
- + }
- +
- + /*
- + A mini software pipelining - consists of two steps
- + 1) try to get the floating point store to be the last instruction
- + executed before the jump at the end of loop.
- + 2) try to get the jump to be executed before the floating point
- + store by retargeting it to the begining of loop and moving
- + the floating point store to there. Note that the fall into the
- + loop will be replaced by a jump around this floating point store
- + If do_all is 0 then just do step 1
- + */
- + static
- + loop_spl (loop_start, loop_end, loop_num, do_all)
- + rtx loop_start, loop_end;
- + int loop_num, do_all;
- + {
- + rtx insn, jump_insn, mem_addr, base_reg, index_reg, copy_pat, label_insn,
- + label, p, *index_where, *base_where, pinsn, cc0_insn, where_to_move;
- + struct reg_incs *reg_inc;
- + int cur_max_regnum, scale;
- + char *storage;
- +
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "loop_spl from %d to %d\n",
- + INSN_UID (loop_start), INSN_UID (loop_end));
- + }
- + cur_max_regnum = max_reg_num () + 1;
- + reg_inc
- + = (struct reg_incs *) alloca (cur_max_regnum * (sizeof (struct reg_incs)));
- + bzero (reg_inc, cur_max_regnum * (sizeof (struct reg_incs)));
- + insn = PREV_INSN (loop_end);
- + while (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
- + && rtx_equal_p (SET_DEST (PATTERN (insn)), SET_SRC (PATTERN (insn))))
- + {
- + insn = PREV_INSN (insn);
- + }
- + if (GET_CODE (insn) != JUMP_INSN)
- + {
- +
- + return;
- + }
- + jump_insn = insn;
- + insn = PREV_INSN (jump_insn);
- + if (!(GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
- + && SET_DEST (PATTERN (insn)) == cc0_rtx))
- + {
- +
- + return;
- + }
- + cc0_insn = insn;
- + base_reg = NULL;
- + index_reg = NULL;
- + scale = 1;
- + insn = prev_nonnote_insn (insn);
- + while (1)
- + {
- + if (GET_CODE (insn) != INSN)
- + {
- +
- + return;
- + }
- + if (GET_CODE (PATTERN (insn)) != SET)
- + {
- +
- + return;
- + }
- + if (GET_CODE (SET_DEST (PATTERN (insn))) == REG
- + && (GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
- + || GET_CODE (SET_SRC (PATTERN (insn))) == MINUS)
- + && rtx_equal_p (SET_DEST (PATTERN (insn)),
- + XEXP (SET_SRC (PATTERN (insn)), 0))
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
- + {
- + reg_inc[REGNO (SET_DEST (PATTERN (insn)))].inc_val
- + += INTVAL (XEXP (SET_SRC (PATTERN (insn)), 1));
- + if (GET_CODE (SET_SRC (PATTERN (insn))) == MINUS)
- + {
- + reg_inc[REGNO (SET_DEST (PATTERN (insn)))].inc_val *= -1;
- + }
- + insn = prev_nonnote_insn (insn);
- + }
- + else
- + {
- + break;
- + }
- + }
- + if (!(GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
- + && (GET_CODE (SET_SRC (PATTERN (insn))) == REG
- + || (GET_CODE (SET_SRC (PATTERN (insn))) == FLOAT_TRUNCATE
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG)
- + || (GET_CODE (SET_SRC (PATTERN (insn))) == FLOAT_EXTEND
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == REG))
- + && GET_CODE (SET_DEST (PATTERN (insn))) == MEM
- + && (GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
- + || GET_MODE (SET_DEST (PATTERN (insn))) == DFmode)
- + && GET_MODE (SET_DEST (PATTERN (insn))) ==
- + GET_MODE (SET_SRC (PATTERN (insn)))
- + )
- + )
- + {
- +
- + return;
- + }
- + /* if previous fp instruction is fld - no gain */
- + pinsn = prev_nonnote_insn (insn);
- + if (INSN_UID (pinsn) < INSN_UID (loop_start))
- + {
- +
- + return;
- + }
- + while (pinsn != loop_start)
- + {
- + if (GET_CODE (pinsn) == JUMP_INSN || GET_CODE (pinsn) == CODE_LABEL
- + || (GET_CODE (pinsn) == INSN && GET_CODE (PATTERN (pinsn)) == SET
- + && (GET_MODE (SET_DEST (PATTERN (pinsn))) == SFmode
- + || GET_MODE (SET_DEST (PATTERN (pinsn))) == DFmode)
- + )
- + )
- + {
- + break;
- + }
- + pinsn = PREV_INSN (pinsn);
- + }
- + if (pinsn == loop_start || GET_CODE (pinsn) == JUMP_INSN
- + || GET_CODE (pinsn) == CODE_LABEL)
- + {
- +
- + return;
- + }
- + if ((GET_CODE (SET_SRC (PATTERN (pinsn))) == MEM
- + || GET_CODE (SET_SRC (PATTERN (pinsn))) == CONST_DOUBLE
- + || GET_CODE (SET_SRC (PATTERN (pinsn))) == REG)
- + )
- + {
- +
- + return;
- + }
- + /* We have found the floating point store insn - now try to move it down */
- + /* Find the registers that are used as bases for the memory access in the
- + insn */
- + storage = (char *) oballoc (0);
- + copy_pat = copy_rtx (PATTERN (insn));
- + mem_addr = XEXP (SET_DEST (copy_pat), 0);
- + if (GET_CODE (mem_addr) == PLUS)
- + {
- + if (GET_CODE (XEXP (mem_addr, 0)) == MULT)
- + {
- + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == REG
- + && GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == CONST_INT)
- + {
- + index_where = &XEXP (XEXP (mem_addr, 0), 0);
- + index_reg = XEXP (XEXP (mem_addr, 0), 0);
- + scale = INTVAL (XEXP (XEXP (mem_addr, 0), 1));
- + }
- + else
- + {
- +
- + return;
- + }
- + if (GET_CODE (XEXP (mem_addr, 1)) == REG)
- + {
- + base_where = &XEXP (mem_addr, 1);
- + base_reg = XEXP (mem_addr, 1);
- + }
- + else if (GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF
- + || GET_CODE (XEXP (mem_addr, 1)) == CONST)
- + {
- + ;
- + }
- + else
- + {
- +
- + return;
- + }
- + }
- + else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS)
- + {
- + /* Take care of non canonicalized expressions */
- + rtx tmp;
- + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == REG
- + && GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == MULT)
- + {
- + tmp = XEXP (XEXP (mem_addr, 0), 0);
- + XEXP (XEXP (mem_addr, 0), 0) = XEXP (XEXP (mem_addr, 0), 1);
- + XEXP (XEXP (mem_addr, 0), 1) = tmp;
- + }
- +
- + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) != MULT)
- + {
- +
- + return;
- + }
- + if (GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == REG
- + && GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) == CONST_INT)
- + {
- + index_where = &XEXP (XEXP (XEXP (mem_addr, 0), 0), 0);
- + index_reg = XEXP (XEXP (XEXP (mem_addr, 0), 0), 0);
- + scale = INTVAL (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1));
- + }
- + else
- + {
- +
- + return;
- + }
- + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) != REG)
- + {
- +
- + return;
- + }
- + base_where = &XEXP (XEXP (mem_addr, 0), 1);
- + base_reg = XEXP (XEXP (mem_addr, 0), 1);
- + if (GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF
- + || GET_CODE (XEXP (mem_addr, 1)) == CONST
- + || GET_CODE (XEXP (mem_addr, 1)) == CONST_INT)
- + {
- + ;
- + }
- + else
- + {
- +
- + return;
- + }
- + }
- + else if (GET_CODE (XEXP (mem_addr, 0)) == REG)
- + {
- + base_where = &XEXP (mem_addr, 0);
- + base_reg = XEXP (mem_addr, 0);
- + if (GET_CODE (XEXP (mem_addr, 1)) == REG)
- + {
- + index_where = &XEXP (mem_addr, 1);
- + index_reg = XEXP (mem_addr, 1);
- + }
- + }
- + else
- + {
- +
- + return;
- + }
- + }
- + else if (GET_CODE (mem_addr) == SYMBOL_REF || GET_CODE (mem_addr) == CONST)
- + {
- + ;
- + }
- + else if (GET_CODE (mem_addr) == REG)
- + {
- + base_reg = mem_addr;
- + base_where = &XEXP (SET_DEST (copy_pat), 0);
- + }
- + else
- + {
- +
- + return;
- + }
- + /* Now we know the base index and scale */
- + if (index_reg && reg_inc[REGNO (index_reg)].inc_val)
- + {
- + *index_where = gen_rtx (PLUS, GET_MODE (index_reg), index_reg,
- + gen_rtx (CONST_INT, 0, reg_inc[REGNO (index_reg)].inc_val * -1));
- + }
- + if (base_reg && reg_inc[REGNO (base_reg)].inc_val)
- + {
- + *base_where = gen_rtx (PLUS, GET_MODE (base_reg), base_reg,
- + gen_rtx (CONST_INT, 0, reg_inc[REGNO (base_reg)].inc_val * -1));
- + }
- + #ifdef REWRITE_ADDRESS
- + if (recog (copy_pat, insn, 0) < 0)
- + {
- + try_to_make_good (SET_DEST (copy_pat));
- + }
- + #endif
- + if (recog (copy_pat, insn, 0) < 0)
- + {
- + obfree (storage);
- +
- + return;
- + }
- + if (do_all == 0)
- + {
- + where_to_move = cc0_insn;
- + }
- + else
- + {
- + where_to_move = jump_insn;
- + }
- + /* Now move the store with it's new pattern */
- + PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
- + NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
- + NEXT_INSN (insn) = where_to_move;
- + PREV_INSN (insn) = PREV_INSN (where_to_move);
- + NEXT_INSN (PREV_INSN (where_to_move)) = insn;
- + PREV_INSN (where_to_move) = insn;
- + PATTERN (insn) = copy_pat;
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " moved fp store down\n");
- + }
- + if (do_all == 0)
- + {
- +
- + return;
- + }
- + /* Now move the store again and add a new jump and label */
- + if (loop_invalid[loop_num])
- + {
- + emit_insn_before (gen_rtx (USE, 0, cc0_rtx), insn);
- +
- + return;
- + }
- + if (GET_CODE (NEXT_INSN (loop_start)) != CODE_LABEL)
- + {
- + emit_insn_before (gen_rtx (USE, 0, cc0_rtx), insn);
- +
- + return;
- + }
- + label_insn = NEXT_INSN (loop_start);
- + if (GET_CODE (SET_SRC (PATTERN (jump_insn))) != IF_THEN_ELSE)
- + {
- + emit_insn_before (gen_rtx (USE, 0, cc0_rtx), insn);
- +
- + return;
- + }
- + #if 0
- + if (LABEL_NUSES (label_insn) != 1)
- + {
- + emit_insn_before (gen_rtx (USE, 0, cc0_rtx), insn);
- +
- + return;
- + }
- + #endif
- + /* Make a jump to the old label just before the label*/
- + p = emit_jump_insn_after (gen_jump (label_insn),
- + PREV_INSN (label_insn));
- + JUMP_LABEL (p) = label_insn;
- + emit_barrier_after (p);
- + /* Add a new label just before the old one */
- + label = gen_label_rtx ();
- + label_insn = emit_label_after (label, PREV_INSN (label_insn));
- + /* Make the jump at the end of the loop jump to the new lable */
- + if (XEXP (SET_SRC (PATTERN (jump_insn)), 1) == pc_rtx)
- + {
- + XEXP (SET_SRC (PATTERN (jump_insn)), 2)
- + = gen_rtx (LABEL_REF, VOIDmode, label);
- + }
- + else
- + {
- + XEXP (SET_SRC (PATTERN (jump_insn)), 1)
- + = gen_rtx (LABEL_REF, VOIDmode, label);
- + }
- + ++LABEL_NUSES (label_insn);
- + JUMP_LABEL (jump_insn) = label_insn;
- + /* Move the store to just after the new label */
- + PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
- + NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
- + NEXT_INSN (insn) = NEXT_INSN (label_insn);
- + PREV_INSN (insn) = label_insn;
- + PREV_INSN (NEXT_INSN (label_insn)) = insn;
- + NEXT_INSN (label_insn) = insn;
- + /* Add the store after the jump at the end of the loop */
- + p = emit_insn_after (PATTERN (insn), jump_insn);
- + REG_NOTES (p) = REG_NOTES (insn);
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " spl successful\n");
- + }
- + }
- +
- + #endif
- + #endif
- +
- + /* Element N is first insn in basic block N.
- + This info lasts until we finish compiling the function. */
- +
- + extern rtx *basic_block_head;
- +
- + /* Element N is last insn in basic block N.
- + This info lasts until we finish compiling the function. */
- +
- + extern rtx *basic_block_end;
- +
- + /* Number of basic blocks in the current function. */
- +
- + extern int n_basic_blocks;
- +
- + extern regset *basic_block_live_at_start;
- +
- + /* Move spills out of loops if possible i.e.
- + if can find a register in the loop that is
- + alway used to hold a certian spill slot then
- + 1) load the spill slot into that register before the
- + loop.
- + 2) replace all refernces to the spill slot int the loop with
- + refernces to that register
- + 3) if the spill slot was updated in the loop and the pseudo
- + that corresponds to that spill slot is alive at the loop
- + fallout then write that register back to the spill slot
- + at the end of the loop. NOTE that if the pseudo is
- + alive at any other of the loop exits (if there are any)
- + and the spill slot is updated in the loop then steps
- + 1) and 2) are NOT done.
- + NOTE
- + a) if the spill slot is only loaded into the register once
- + throughout the loop and the spill slot is not updated in
- + the loop then loop_optimize() called from here will
- + probably handle this. I say probably because maybe_never
- + of scan_loop is rather over cautious since it is set
- + when a jump_insn is encountered but not reset when
- + the corresponding label is encountered.
- +
- +
- + Other optimizations which are done here are trying
- + to push invariants that were spilled back into the loop
- + (see push_load_into_loop()).
- +
- + Also a straight line pass over the function is made
- + and whenever a spill slot is loaded into a register
- + if that spill slot is also valid in some register
- + then that spill slot is replaced with that register.
- + (see peep_spills()).
- +
- + */
- + void
- + loop_after_global (f, dumpfile)
- + /* f is the first instruction of a chain of insns for one function */
- + rtx f;
- + FILE *dumpfile;
- + {
- + rtx insn;
- + int i;
- + rtx nonlocal_label_list = nonlocal_label_rtx_list ();
- + register regset tem;
- +
- + int sav_flag_copy_prop;
- + int sav_flag_jump_back;
- + int sav_flag_compare_elim;
- + int sav_flag_unroll_loops;
- + int sav_flag_strength_reduce;
- +
- +
- + sav_flag_copy_prop = flag_copy_prop;
- + sav_flag_jump_back = flag_jump_back;
- + sav_flag_compare_elim = flag_compare_elim;
- + sav_flag_unroll_loops = flag_unroll_loops;
- + sav_flag_strength_reduce = flag_strength_reduce;
- +
- + flag_copy_prop = 0;
- + flag_jump_back = 0;
- + flag_compare_elim = 0;
- + flag_unroll_loops = 0;
- + flag_strength_reduce = 0;
- +
- + cur_stack_offset = 0;
- + doing_loop_after_global = 1;
- + loop_optimize (f, dumpfile);
- + doing_loop_after_global = 0;
- + { /* Update basic block start and ends */
- + register RTX_CODE prev_code = JUMP_INSN;
- + register RTX_CODE code;
- + for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
- + {
- + code = GET_CODE (insn);
- + if (code == CODE_LABEL
- + || (GET_RTX_CLASS (code) == 'i'
- + && (prev_code == JUMP_INSN
- + || (prev_code == CALL_INSN
- + && nonlocal_label_list != 0)
- + || prev_code == BARRIER)))
- + i++;
- + if (code != NOTE)
- + prev_code = code;
- + }
- + if (i > n_basic_blocks)
- + {
- + n_basic_blocks = i;
- + basic_block_head = (rtx *) oballoc (n_basic_blocks * sizeof (rtx));
- + basic_block_end = (rtx *) oballoc (n_basic_blocks * sizeof (rtx));
- + }
- + n_basic_blocks = i;
- + prev_code = JUMP_INSN;
- + for (insn = f, i = -1; insn; insn = NEXT_INSN (insn))
- + {
- + code = GET_CODE (insn);
- + /* A basic block starts at label, or after something that can jump. */
- + if (code == CODE_LABEL
- + || (GET_RTX_CLASS (code) == 'i'
- + && (prev_code == JUMP_INSN
- + || (prev_code == CALL_INSN
- + && nonlocal_label_list != 0)
- + || prev_code == BARRIER)))
- + {
- + basic_block_head[++i] = insn;
- + if (i >= n_basic_blocks)
- + {
- + abort ();
- + }
- + basic_block_end[i] = insn;
- + }
- + else if (GET_RTX_CLASS (code) == 'i')
- + {
- + basic_block_end[i] = insn;
- + }
- +
- + if (code != NOTE
- + && !(prev_code == CALL_INSN && code == INSN
- + && GET_CODE (PATTERN (insn)) == CLOBBER))
- + prev_code = code;
- + }
- + }
- + flag_copy_prop = sav_flag_copy_prop;
- + flag_jump_back = sav_flag_jump_back;
- + flag_compare_elim = sav_flag_compare_elim;
- + flag_unroll_loops = sav_flag_unroll_loops;
- + flag_strength_reduce = sav_flag_strength_reduce;
- +
- + }
- +
- + /* x is a spill slot and hence is unaliased
- + */
- +
- + static int
- + spill_invariant_p (x)
- + register rtx x;
- + {
- + register int i;
- + register enum rtx_code code;
- + register char *fmt;
- + int conditional = 0;
- +
- + if (x == 0)
- + return 1;
- + code = GET_CODE (x);
- + switch (code)
- + {
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CONST:
- + return 1;
- +
- + case LABEL_REF:
- + /* A LABEL_REF is normally invariant, however, if we are unrolling
- + loops, and this label is inside the loop, then it isn't invariant.
- + This is because each unrolled copy of the loop body will have
- + a copy of this label. If this was invariant, then an insn loading
- + the address of this label into a register might get moved outside
- + the loop, and then each loop body would end up using the same label.
- +
- + We don't know the loop bounds here though, so just fail for all
- + labels. */
- + if (flag_unroll_loops)
- + return 0;
- + else
- + return 1;
- +
- + case PC:
- + case CC0:
- + case UNSPEC_VOLATILE:
- + return 0;
- +
- + case REG:
- + /* We used to check RTX_UNCHANGING_P (x) here, but that is invalid
- + since the reg might be set by initialization within the loop. */
- + if (x == frame_pointer_rtx || x == arg_pointer_rtx)
- + return 1;
- + if (loop_has_call
- + && REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
- + return 0;
- + if (n_times_set[REGNO (x)] < 0)
- + return 2;
- + return n_times_set[REGNO (x)] == 0;
- +
- + case MEM:
- + /* Read-only items (such as constants in a constant pool) are
- + invariant if their address is. */
- + if (RTX_UNCHANGING_P (x))
- + break;
- +
- + /* If we filled the table (or had a subroutine call), any location
- + in memory could have been clobbered. */
- + if (unknown_address_altered
- + /* Don't mess with volatile memory references. */
- + || MEM_VOLATILE_P (x))
- + return 0;
- +
- + /* See if there is any dependence between a store and this load. */
- + for (i = loop_store_mems_idx - 1; i >= 0; i--)
- + if (rtx_equal_p (XEXP (loop_store_mems[i], 0), XEXP (x, 0)))
- + {
- + return 0;
- + }
- +
- + /* It's not invalidated by a store in memory
- + but we must still verify the address is invariant. */
- + break;
- +
- + case ASM_OPERANDS:
- + /* Don't mess with insns declared volatile. */
- + if (MEM_VOLATILE_P (x))
- + return 0;
- + }
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + {
- + if (fmt[i] == 'e')
- + {
- + int tem = invariant_p (XEXP (x, i));
- + if (tem == 0)
- + return 0;
- + if (tem == 2)
- + conditional = 1;
- + }
- + else if (fmt[i] == 'E')
- + {
- + register int j;
- + for (j = 0; j < XVECLEN (x, i); j++)
- + {
- + int tem = invariant_p (XVECEXP (x, i, j));
- + if (tem == 0)
- + return 0;
- + if (tem == 2)
- + conditional = 1;
- + }
- +
- + }
- + }
- +
- + return 1 + conditional;
- + }
- +
- + extern struct reload_slot_info reload_slots[];
- + extern num_reload_stack_slots;
- + extern char call_used_regs[];
- + extern char **insn_name_ptr;
- +
- +
- + static struct spill_candidates
- + {
- + /* The stack slot reloaded into this candidate */
- + rtx reload_slot;
- + /* The insn that does the reloading */
- + rtx reload_insn;
- + /* The rtx of the hard register that is reloaded into */
- + rtx hard_reg;
- + /* The mode of the reload slot */
- + enum machine_mode mode;
- + /* Number of times this candidate is set */
- + int num_times_set;
- + /* The pseduo register corresponding to the stack slot */
- + int pseudo_reg;
- + int cur_stack_offset;
- + int reload_indx;
- + /* A linked list of candidates on the same reload stack slot */
- + struct spill_candidates *link_cand;
- + struct spill_candidates *head_cand;
- + unsigned is_head:1;
- + unsigned has_link:1;
- + /* if 1 this candidate is invalid */
- + unsigned disregard:1;
- + /* if 1 the reload stack slot is stored into */
- + unsigned slot_updated_in_loop:1;
- + /* if 1 the pseduo register is live at the loop fall out */
- + unsigned live_at_fall_out:1;
- + /* if 1 the pseduo register is live at a loop jump out */
- + unsigned live_at_jump_out:1;
- + /* if 1 the value in the candidate hard register must be
- + updated into the reload stack slot */
- + unsigned must_update_reload:1;
- + /* if 1 then the candidate hard register was loaded with the
- + reload stack slot before it was used */
- + unsigned first_set_to_reload:1;
- + /* if 1 then the candidate's spill slot has been updated and
- + the candidate is out of synch with it's spill slot intel1a */
- + unsigned slot_updated:1;
- + }
- +
- + spill_candidate[FIRST_PSEUDO_REGISTER];
- +
- + static int all_candidates_invalid = 0;
- + static int num_spill_candidates_found = 0;
- + static int *insns_moved_out;
- + static int have_flow_analysis = 0;
- +
- + /* Find all candidates for spill slot optimization over the loop and
- + move them out. Also try to push spilled invariants back into the
- + loop
- + */
- + static
- + void
- + move_spills_out (loop_start, loop_end)
- + rtx loop_start;
- + rtx loop_end;
- + {
- + rtx insn;
- + int i, is_loop_exit, regno, indx;
- +
- + insns_moved_out = (int *) alloca ((max_uid_for_loop + 1) * sizeof (int));
- + bzero (insns_moved_out, (max_uid_for_loop + 1) * sizeof (int));
- + num_reload_stack_slots = 0;
- + num_spill_candidates_found = 0;
- + bzero (spill_candidate, FIRST_PSEUDO_REGISTER * sizeof (spill_candidate[0]));
- + for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
- + {
- + spill_candidate[i].reload_indx = -1;
- + }
- + insn = loop_start;
- + while (insn != PREV_INSN (loop_end))
- + {
- + if (GET_CODE (insn) == INSN && RTX_IS_SPILL_P (insn)
- + && GET_CODE (PATTERN (insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (insn))) == MEM
- + && is_a_stack_slot (SET_SRC (PATTERN (insn)))
- + && (regno = REGNO (SET_DEST (PATTERN (insn)))) < FIRST_PSEUDO_REGISTER
- + )
- + {
- + indx = -1;
- + if (!is_a_reload_stack_slot (SET_SRC (PATTERN (insn)), &indx, 0, 0))
- + {
- + if (num_reload_stack_slots >= MAX_RELOAD_STACK_SLOTS)
- + {
- + return;
- + }
- + reload_slots[num_reload_stack_slots].cur_stack_offset = 0;
- + reload_slots[num_reload_stack_slots].reload_stack_mode = -1;
- + reload_slots[num_reload_stack_slots].is_loaded_to_reg = -1;
- + reload_slots[num_reload_stack_slots].reload_slot_updated = 0;
- + reload_slots[num_reload_stack_slots].stack_slot_pseudo_reg
- + = SPILL_PSEUDO (insn);
- + reload_slots[num_reload_stack_slots].reload_insn = insn;
- + reload_slots[num_reload_stack_slots++].reload_stack_slot
- + = SET_SRC (PATTERN (insn));
- + }
- + else
- + { /* We have already encountered this reload slot - it
- + must always be a reload slot of the same pseudo */
- + if (reload_slots[indx].stack_slot_pseudo_reg !=
- + SPILL_PSEUDO (insn))
- + {
- + reload_slots[indx].reload_stack_mode == -2;
- + }
- + }
- + if (indx == -1)
- + {
- + indx = num_reload_stack_slots - 1;
- + }
- + if (!(spill_candidate[regno].pseudo_reg == 0
- + || spill_candidate[regno].pseudo_reg == SPILL_PSEUDO (insn)))
- + { /* Candidate can be for only one spilled pseudo reg */
- + reload_slots[indx].reload_stack_mode = -2;
- + if (spill_candidate[regno].reload_indx != -1)
- + {
- + reload_slots[spill_candidate[regno].reload_indx].reload_stack_mode = -2;
- + }
- + }
- + else if (spill_candidate[regno].reload_indx != -1
- + && spill_candidate[regno].reload_indx != indx)
- + { /* Candidates can only be for one reload slot */
- + reload_slots[indx].reload_stack_mode = -2;
- + reload_slots[spill_candidate[regno].reload_indx].reload_stack_mode = -2;
- + }
- + else
- + {
- + spill_candidate[regno].pseudo_reg = SPILL_PSEUDO (insn);
- + spill_candidate[regno].reload_indx = indx;
- + }
- + }
- + insn = NEXT_INSN (insn);
- + }
- +
- + all_candidates_invalid = 0;
- + insn = loop_start;
- + while (insn != (loop_end))
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + mark_spill_candidates (insn, PATTERN (insn));
- + if (all_candidates_invalid)
- + {
- + return;
- + }
- + }
- + else if (GET_CODE (insn) == JUMP_INSN)
- + { /* Check if this is a loop exit */
- + is_loop_exit = check_if_jumps_out_of_loop (PATTERN (insn), 1);
- + /* Verify which spill candidates remian valid */
- + if (num_spill_candidates_found)
- + verify_spill_candidates (insn, is_loop_exit);
- + if (all_candidates_invalid)
- + {
- + return;
- + }
- + }
- + else if (GET_CODE (insn) == CODE_LABEL && num_spill_candidates_found)
- + {
- + /* Verify which spill candidates remian valid */
- + verify_spill_candidates (insn, 0);
- + }
- + insn = NEXT_INSN (insn);
- + }
- + if (num_spill_candidates_found && !all_candidates_invalid)
- + {
- + int i;
- + rtx rn, prev, link;
- + if (!simplejump_p (PREV_INSN (loop_end)))
- + mark_regs_alive_at_exit (NEXT_INSN (loop_end), 1);
- + if (!all_candidates_invalid)
- + {
- + move_spill_movables (loop_start, loop_end);
- +
- + for (rn = loop_start; rn != loop_end; rn = NEXT_INSN (rn))
- + {
- + if ((GET_CODE (rn) == INSN || GET_CODE (rn) == JUMP_INSN
- + || GET_CODE (rn) == CALL_INSN) && LOG_LINKS (rn))
- + {
- + for (prev = 0, link = LOG_LINKS (rn); link;
- + prev = link, link = XEXP (link, 1))
- + {
- + if (insns_moved_out[INSN_UID (XEXP (link, 0))])
- + {
- + if (prev)
- + XEXP (prev, 1) = XEXP (link, 1);
- + else
- + LOG_LINKS (rn) = XEXP (link, 1);
- + }
- + }
- +
- + }
- + }
- + }
- + }
- + if (unknown_address_altered)
- + {
- + return;
- + }
- + for (i = 0; i < num_reload_stack_slots; i++)
- + {
- + if (flag_push_load_into_loop
- + && reload_slots[i].reload_slot_updated == 0
- + /*&& reload_slots[i].reload_stack_mode != -2
- + && reload_slots[i].is_loaded_to_reg != -1
- + && !spill_candidate[reload_slots[i].is_loaded_to_reg].has_link
- + && spill_candidate[reload_slots[i].is_loaded_to_reg].disregard
- + && spill_candidate[reload_slots[i].is_loaded_to_reg].live_at_jump_out == 0
- + && spill_candidate[reload_slots[i].is_loaded_to_reg].live_at_fall_out == 0
- + */
- + )
- + {
- + /* This is a reload slot that was never updated in loop
- + but could not be lifted only because the register it is
- + loaded into was also set to something else in loop.
- + Lets see if the reload slot was set in the basic block
- + just prior to the loop by some inexpensive operation.
- + (particularly a move from memory into a register and
- + a move of that register onto stack). If so lets
- + replace each load of the reload slot in the loop with
- + a load of the memory and delete the code that loaded
- + and spilled it outside the loop.
- + This corrects the preloading of loop invariants that
- + could not be held in registers over the loop
- + */
- + push_load_into_loop (loop_start, loop_end, i);
- + }
- + }
- + }
- +
- + /* Move the valid spill slot candidates out of the loop and
- + replace the spill slot with the register throughout the loop.
- + Also update the spill slot after the loop if this is necessary */
- +
- + static
- + void
- + move_spill_movables (loop_start, loop_end)
- + rtx loop_start, loop_end;
- + {
- + rtx insn;
- + int i, indx, all_are_ok;
- + struct spill_candidates *link_cand;
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + if (spill_candidate[i].disregard == 0 && spill_candidate[i].reload_insn
- + && spill_candidate[i].num_times_set == n_times_set[i])
- + {
- + is_a_reload_stack_slot (spill_candidate[i].reload_slot, &indx, 0, 0);
- + /* Sanity check */
- + if (spill_candidate[i].reload_indx != indx)
- + {
- + abort ();
- + }
- + if (reload_slots[indx].reload_stack_mode == -2)
- + {/* The stack slot was used in some other mode than the
- + load to the hard reg */
- + spill_candidate[i].disregard = 1;
- + continue;
- + }
- + if (!spill_candidate[i].has_link)
- + {
- + all_are_ok = 1;
- + }
- + else if (spill_candidate[i].is_head)
- + {
- + /* This is a candidate that is the head of a chain of
- + candidates that all contain the same reload slot.
- + Go over the linked list to see if all are ok;
- + */
- + all_are_ok = 1;
- + link_cand = spill_candidate[i].link_cand;
- + while (link_cand)
- + {
- + all_are_ok = all_are_ok
- + && link_cand->disregard == 0
- + && link_cand->num_times_set == 1
- + && n_times_set[REGNO (link_cand->hard_reg)] == 1
- + && link_cand->reload_insn;
- + /* So it won't be processed again */
- + link_cand->disregard = 1;
- + link_cand = link_cand->link_cand;
- + }
- + if (spill_candidate[i].num_times_set != 1)
- + {
- + all_are_ok = 0;
- + }
- + if (all_are_ok == 0)
- + {
- + spill_candidate[i].disregard = 1;
- + }
- + }
- + else
- + {
- + all_are_ok = 0;
- + }
- + if (all_are_ok)
- + {
- + /* Move the reload insn to just before loop_start */
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream,
- + "insn %d moved out of loop, stack slot held in reg %d over loop\n",
- + INSN_UID (spill_candidate[i].reload_insn), i);
- + if (spill_candidate[i].is_head)
- + {
- + fprintf (loop_dump_stream, " these regs also shadow the stack slot:");
- + link_cand = spill_candidate[i].link_cand;
- + while (link_cand)
- + {
- + fprintf (loop_dump_stream, " %d", REGNO (link_cand->hard_reg));
- + link_cand = link_cand->link_cand;
- + }
- + fprintf (loop_dump_stream, "\n");
- + }
- + }
- + insn = spill_candidate[i].reload_insn;
- + NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
- + PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
- + NEXT_INSN (insn) = loop_start;
- + PREV_INSN (insn) = PREV_INSN (loop_start);
- + NEXT_INSN (PREV_INSN (loop_start)) = insn;
- + PREV_INSN (loop_start) = insn;
- + if (INSN_UID (insn) <= max_uid_for_loop)
- + {
- + insns_moved_out[INSN_UID (insn)] = 1;
- + }
- + if (spill_candidate[i].live_at_fall_out
- + && spill_candidate[i].slot_updated_in_loop)
- + {
- + emit_insn_after (gen_rtx (SET, 0, spill_candidate[i].reload_slot,
- + spill_candidate[i].hard_reg),
- + loop_end);
- + }
- + }
- + }
- + else
- + {
- + spill_candidate[i].disregard = 1;
- + if (spill_candidate[i].has_link && spill_candidate[i].is_head)
- + { /* invalidate the whole chain */
- + link_cand = spill_candidate[i].link_cand;
- + while (link_cand)
- + {
- + link_cand->disregard = 1;
- + link_cand = link_cand->link_cand;
- + }
- + }
- + }
- + }
- + /* Where ever a reload_slot that is contained is a valid candidate
- + appears in the loop - replace it with that hard_reg */
- + insn = loop_start;
- + while (insn != loop_end)
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + undobuf.num_undo = 0;
- + undobuf.storage = (char *) oballoc (0);
- + replace_spill_slots (insn, PATTERN (insn), &PATTERN (insn));
- + replace_linked_regs (insn, PATTERN (insn));
- + }
- + insn = NEXT_INSN (insn);
- + }
- +
- + }
- +
- +
- + /* If pat jumps out of the loop then mark all candidates that
- + correspond to pseudos that are alive at the target of the jump,
- + and return 1
- + */
- + static
- + int
- + check_if_jumps_out_of_loop (pat, do_mark)
- + rtx pat;
- + int do_mark;
- + {
- + rtx target;
- + int ret_val = 0;
- + int i;
- +
- + switch (GET_CODE (pat))
- + {
- + case PC:
- + case USE:
- + case CLOBBER:
- + case REG:
- + case MEM:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case RETURN:
- + return (ret_val);
- +
- + case CONST:
- + /* There could be a label reference in here. */
- + return (check_if_jumps_out_of_loop (XEXP (pat, 0), do_mark));
- +
- + case PLUS:
- + case MINUS:
- + case MULT:
- + case LSHIFT:
- + ret_val = check_if_jumps_out_of_loop (XEXP (pat, 0), do_mark);
- + ret_val = ret_val | check_if_jumps_out_of_loop (XEXP (pat, 1), do_mark);
- + return (ret_val);
- +
- + case SIGN_EXTEND:
- + case ZERO_EXTEND:
- + return (check_if_jumps_out_of_loop (XEXP (pat, 0), do_mark));
- +
- + case LABEL_REF:
- + if (LABEL_OUTSIDE_LOOP_P (pat))
- + { /* This is a jump to outside of loop */
- + if (do_mark)
- + {
- + target = XEXP (pat, 0);
- + /* Now mark all those pseudo regs not dead at entry
- + to the target block */
- + mark_regs_alive_at_exit (target, 0);
- + }
- + ret_val = 1;
- + }
- +
- + return (ret_val);;
- +
- + case SET:
- + /* If this is not setting pc, ignore. */
- + if (SET_DEST (pat) == pc_rtx)
- + ret_val = check_if_jumps_out_of_loop (SET_SRC (pat), do_mark);
- + return (ret_val);
- +
- + case IF_THEN_ELSE:
- + ret_val = check_if_jumps_out_of_loop (XEXP (pat, 1), do_mark);
- + ret_val = ret_val | check_if_jumps_out_of_loop (XEXP (pat, 2), do_mark);
- + return (ret_val);
- +
- + case PARALLEL:
- + case ADDR_VEC:
- + case ADDR_DIFF_VEC:
- + all_candidates_invalid = 1;
- + return(1);
- +
- + default:
- + /* Nothing else should occur in a JUMP_INSN. */
- + abort ();
- + }
- + }
- +
- + /*
- + block_head, or the first nonnote insn after block_head (if block_head
- + is a note insn), is the head of a block that is the target of a loop
- + exit. if is_loop_fallout is 1 then the loop exit is the normal end of
- + the loop where the loop falls out, otherwise the loop exit was a jump
- + out of the loop. Any candidates whose pseudos are alive at the
- + start of the block are marked (i.e. the stack slot which
- + corresponds to the pseudo must be updated at this loop exit)
- + if the loop exit is NOT the loop fallout then we mark this
- + candidate as not valid
- + */
- +
- + static
- + void
- + mark_regs_alive_at_exit (block_head, is_loop_fallout)
- + rtx block_head;
- + int is_loop_fallout;
- + {
- + int i, found, pseudo_regno, block_num, offset, bit;
- + rtx org_block_head = block_head;
- +
- + i = 0;
- + found = 0;
- + /* Find which block block_head is the head of */
- + if (is_loop_fallout)
- + {
- + while (i < n_basic_blocks && !found)
- + {
- + if (basic_block_head[i] == block_head)
- + {
- + found = 1;
- + }
- + else
- + {
- + i++;
- + }
- + }
- + }
- + if (!found)
- + {
- + while (block_head && GET_CODE (block_head) != CODE_LABEL
- + && GET_RTX_CLASS (GET_CODE (block_head)) != 'i')
- + {
- + block_head = NEXT_INSN (block_head);
- + }
- + if (block_head == NULL)
- + {
- + if (!is_loop_fallout)
- + { /* block_head must have been a label upon entry and hence
- + should not be null now */
- + abort ();
- + }
- + return;
- + }
- + i = 0;
- + while (i < n_basic_blocks && !found)
- + {
- + if (basic_block_head[i] == block_head)
- + {
- + found = 1;
- + }
- + else
- + {
- + i++;
- + }
- + }
- + }
- + if (!found)
- + {
- + all_candidates_invalid = 1;
- + return;
- + }
- + block_num = i;
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + if (spill_candidate[i].reload_slot == NULL)
- + { /* A jump out of the loop before it is known
- + if this slot will become a candidate - so
- + just mark it to never become a candidate.
- + Actually we could remember this jump and
- + mark the candidate accordingly in the future
- + but this seems like too much work */
- + spill_candidate[i].disregard = 1;
- + }
- + else
- + if (spill_candidate[i].disregard == 0
- + && spill_candidate[i].reload_slot)
- + { /* This candidate is still valid */
- + /* Find the pseudo reg that corresponds to this spill slot */
- + pseudo_regno = spill_candidate[i].pseudo_reg;
- + if (pseudo_regno < FIRST_PSEUDO_REGISTER)
- + {
- + abort ();
- + }
- + /* See if this pseudo reg is alive at the beginning of
- + the block that begins at block_head*/
- + offset = pseudo_regno / REGSET_ELT_BITS;
- + bit = 1 << (pseudo_regno % REGSET_ELT_BITS);
- + if (basic_block_live_at_start[block_num][offset] & bit)
- + {
- + if (!is_loop_fallout)
- + { /* Don't want to handle pseudo's that are alive
- + at targets of jumps out of the loop */
- + spill_candidate[i].disregard = 1;
- + spill_candidate[i].live_at_jump_out = 1;
- + }
- + else
- + {
- + spill_candidate[i].live_at_fall_out = 1;
- + }
- + }
- + }
- + }
- +
- + }
- +
- +
- + /*
- + Verfiy that all spill candidates are still valid
- + */
- + static
- + void
- + verify_spill_candidates (insn, is_loop_exit)
- + rtx insn;
- + int is_loop_exit;
- + {
- + int i;
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + /* intel1a */
- + spill_candidate[i].slot_updated = 0;
- + if (spill_candidate[i].must_update_reload)
- + {
- + spill_candidate[i].disregard = 1;
- + }
- + if (GET_CODE (insn) == CODE_LABEL)
- + {
- + spill_candidate[i].first_set_to_reload = 0;
- + }
- + }
- + }
- +
- + #ifndef max
- + #define max(a,b) ((a) < (b) ? (b) : (a))
- + #endif
- +
- + /* Update the spill slot candidate info according to what body does */
- + static
- + void
- + mark_spill_candidates (insn, body)
- + rtx insn;
- + rtx body;
- + {
- + int regno, i, dummy, indx, cand_num, j, n_regs;
- +
- +
- + if (GET_CODE (body) == SET)
- + {
- + if (GET_CODE (SET_DEST (body)) != REG
- + && GET_CODE (SET_DEST (body)) != SUBREG)
- + {
- + spill_handle_regs_mentioned (SET_DEST (body));
- + }
- + spill_handle_regs_mentioned (SET_SRC (body));
- + if (GET_CODE (SET_DEST (body)) == SUBREG
- + && GET_CODE (SUBREG_REG (SET_DEST (body))) == REG
- + && REGNO (SUBREG_REG (SET_DEST (body))) < FIRST_PSEUDO_REGISTER)
- +
- + {
- + regno = REGNO (SUBREG_REG (SET_DEST (body)));
- + n_regs
- + = max (HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body))),
- + HARD_REGNO_NREGS (regno,
- + GET_MODE (SUBREG_REG (SET_DEST (body)))));
- + for (j = 0; j < n_regs; j++)
- + {
- + spill_candidate[regno + j].disregard = 1;
- + if (spill_candidate[regno + j].reload_indx != -1)
- + {
- + reload_slots[spill_candidate[regno + j].
- + reload_indx].reload_stack_mode = -2;
- + }
- + }
- + }
- + else if (GET_CODE (SET_DEST (body)) == REG
- + && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER)
- + {
- + /* if body sets a hard register it is of interest */
- + regno = REGNO (SET_DEST (body));
- + n_regs = HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body)));
- + if (n_regs > 1)
- + {
- + for (j = 0; j < n_regs; j++)
- + {
- + spill_candidate[regno + j].disregard = 1;
- + }
- + }
- + spill_candidate[regno].num_times_set++;
- + if (GET_CODE (SET_SRC (body)) == MEM
- + && is_a_reload_stack_slot (SET_SRC (body), &indx, 0, 0))
- + { /* It sets it to the value in a reload stack slot
- + The stack slot must always be used in the same mode
- + as it is used to reload the hard register
- + */
- + /* intel1a */
- + spill_candidate[regno].slot_updated = 0;
- + if (reload_slots[indx].reload_stack_mode == -1)
- + {
- + reload_slots[indx].reload_stack_mode
- + = GET_MODE (SET_SRC (body));
- + }
- + else if (reload_slots[indx].reload_stack_mode == -2
- + || reload_slots[indx].reload_stack_mode
- + != GET_MODE (SET_SRC (body)))
- + {
- + /* reload slot not always used in same mode */
- + reload_slots[indx].reload_stack_mode = -2;
- + spill_candidate[regno].disregard = 1;
- + }
- + if (!spill_candidate[regno].disregard)
- + {
- + if (spill_candidate[regno].reload_indx != -1
- + && spill_candidate[regno].reload_indx != indx)
- + { /* Same reg loads more than one reload slot -
- + disregard it */
- + reload_slots[indx].reload_stack_mode = -2;
- + reload_slots[spill_candidate[regno].reload_indx].reload_stack_mode = -2;
- + spill_candidate[regno].disregard = 1;
- + }
- + else
- + {
- + num_spill_candidates_found++;
- + spill_candidate[regno].first_set_to_reload = 1;
- + spill_candidate[regno].reload_slot
- + = SET_SRC (body);
- + spill_candidate[regno].hard_reg
- + = SET_DEST (body);
- + spill_candidate[regno].reload_insn = insn;
- + spill_candidate[regno].mode
- + = GET_MODE (SET_DEST (body));
- + /* Sanity check */
- + if (spill_candidate[regno].reload_indx != indx
- + && spill_candidate[regno].reload_indx != -1)
- + {
- + abort ();
- + }
- + spill_candidate[regno].reload_indx = indx;
- + if (spill_candidate[regno].slot_updated_in_loop == 0)
- + {
- + spill_candidate[regno].slot_updated_in_loop
- + = reload_slots[indx].reload_slot_updated;
- + }
- + if (spill_candidate[regno].pseudo_reg == 0)
- + {
- + spill_candidate[regno].disregard = 1;
- + }
- + }
- + }
- + if (reload_slots[indx].is_loaded_to_reg == -1)
- + {
- + if (reload_slots[indx].reload_stack_mode != -2
- + && spill_candidate[regno].disregard == 0)
- + {
- + reload_slots[indx].is_loaded_to_reg = regno;
- + }
- + }
- + else if (regno != reload_slots[indx].is_loaded_to_reg)
- + {
- + int loaded_reg;
- + loaded_reg = reload_slots[indx].is_loaded_to_reg;
- + /* Same spill slot already loaded to different hard reg */
- + /* Create a linked list of candidates that load the
- + same reload slot */
- + if (spill_candidate[reload_slots[indx].is_loaded_to_reg].disregard == 0
- + && GET_MODE (reload_slots[indx].reload_stack_slot)
- + == GET_MODE (SET_SRC (body)))
- + {
- + if (spill_candidate[regno].has_link == 0)
- + {
- + spill_candidate[regno].has_link = 1;
- + spill_candidate[loaded_reg].has_link = 1;
- + spill_candidate[loaded_reg].is_head = 1;
- + spill_candidate[regno].link_cand
- + = spill_candidate[loaded_reg].link_cand;
- + spill_candidate[loaded_reg].link_cand
- + = &spill_candidate[regno];
- + spill_candidate[regno].head_cand
- + = &spill_candidate[loaded_reg];
- + }
- + }
- + else
- + {
- + spill_candidate[loaded_reg].disregard = 1;
- + spill_candidate[regno].disregard = 1;
- + reload_slots[indx].reload_stack_mode = -2;
- + }
- + }
- + }
- + else
- + {
- + /* reg regno is set to some other value than
- + a spill stack slot */
- + if (!is_updated_by_const (insn))
- + {
- + spill_candidate[regno].disregard = 1;
- + if (spill_candidate[regno].reload_indx != -1)
- + {
- + reload_slots[spill_candidate[regno].reload_indx].reload_stack_mode = -2;
- + }
- + }
- + /* It sets it to some other value - signal that by
- + the end of this block that value must have been
- + stored into the hard registers reload stack slot
- + */
- + spill_candidate[regno].must_update_reload = 1;
- + }
- + }
- + else if (is_a_reload_stack_slot (SET_DEST (body), &indx, 0, 0))
- + { /* This is an update of a reload_stack_slot */
- + if (GET_CODE (SET_DEST (body)) == SUBREG)
- + {
- + reload_slots[indx].reload_stack_mode = -2;
- + }
- + reload_slots[indx].reload_slot_updated = 1;
- + cand_num = reload_slots[indx].is_loaded_to_reg;
- + /* intel1a */
- + if (cand_num != -1)
- + {
- + spill_candidate[cand_num].slot_updated = 1;
- + }
- + if (cand_num == -1)
- + {
- + if (!is_updated_by_const_or_reg (insn))
- + {
- + /* An update before a load - must not
- + become a candidate */
- + reload_slots[indx].reload_stack_mode = -2;
- + }
- + }
- + else if (GET_CODE (SET_SRC (body)) == REG
- + && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
- + && GET_MODE (SET_SRC (body)) ==
- + spill_candidate[REGNO (SET_SRC (body))].mode
- + && rtx_equal_p (
- + XEXP (spill_candidate[REGNO (SET_SRC (body))].reload_slot, 0),
- + XEXP (SET_DEST (body), 0))
- + )
- + {
- + /* It is an update from the appropriate hard reg
- + and was expected */
- + spill_candidate[cand_num].must_update_reload = 0;
- + spill_candidate[cand_num].slot_updated_in_loop = 1;
- + }
- + else if (spill_candidate[cand_num].must_update_reload != 0)
- + { /* It was expected to be updated by the hard
- + register but it wasn't - the hard register
- + that has this as a reload stack slot is no
- + longer to be considered a candidate */
- + spill_candidate[cand_num].disregard = 1;
- + if (spill_candidate[cand_num].reload_indx != -1)
- + {
- + reload_slots[spill_candidate[cand_num].reload_indx].reload_stack_mode = -2;
- + }
- + }
- + else if (!is_updated_by_const_or_reg (insn))
- + {
- + spill_candidate[cand_num].disregard = 1;
- + if (spill_candidate[cand_num].reload_indx != -1)
- + {
- + reload_slots[spill_candidate[cand_num].reload_indx].reload_stack_mode = -2;
- + }
- + }
- + else
- + {
- + spill_candidate[cand_num].slot_updated_in_loop = 1;
- + }
- + }
- + }
- + else if (GET_CODE (body) == CLOBBER)
- + {
- + if (GET_CODE (SET_DEST (body)) == REG
- + && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER)
- + {
- + regno = REGNO (SET_DEST (body));
- + n_regs = HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body)));
- + for (j = 0; j < n_regs; j++)
- + {
- + spill_candidate[regno + j].disregard = 1;
- + if (spill_candidate[regno + j].reload_indx != -1)
- + {
- + reload_slots[spill_candidate[regno + j].
- + reload_indx].reload_stack_mode = -2;
- + }
- + }
- + }
- + else if (GET_CODE (SET_DEST (body)) == SUBREG
- + && GET_CODE (SUBREG_REG (SET_DEST (body))) == REG
- + && REGNO (SUBREG_REG (SET_DEST (body))) < FIRST_PSEUDO_REGISTER)
- +
- + {
- + regno = REGNO (SUBREG_REG (SET_DEST (body)));
- + n_regs
- + = max (HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body))),
- + HARD_REGNO_NREGS (regno,
- + GET_MODE (SUBREG_REG (SET_DEST (body)))));
- + for (j = 0; j < n_regs; j++)
- + {
- + spill_candidate[regno + j].disregard = 1;
- + if (spill_candidate[regno + j].reload_indx != -1)
- + {
- + reload_slots[spill_candidate[regno + j].
- + reload_indx].reload_stack_mode = -2;
- + }
- + }
- + }
- + }
- + else if (GET_CODE (body) == PARALLEL)
- + {
- + for (i = 0; i < XVECLEN (body, 0); i++)
- + mark_spill_candidates (insn, XVECEXP (body, 0, i));
- + }
- + else
- + {
- + all_candidates_invalid = 1;
- + }
- + }
- +
- +
- + /*
- + Called to mark cnadidates that are invalid at this point */
- + static
- + void
- + spill_handle_regs_mentioned (pat)
- + rtx pat;
- + {
- + register char *fmt;
- + register int i;
- + register enum rtx_code code;
- + int indx;
- +
- + code = GET_CODE (pat);
- +
- + switch (code)
- + {
- + case REG:
- + if (REGNO (pat) < FIRST_PSEUDO_REGISTER)
- + {
- + /* intel1a */
- + if (spill_candidate[REGNO (pat)].slot_updated)
- + {
- + spill_candidate[REGNO (pat)].disregard = 1;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == REGNO (pat))
- + {
- + reload_slots[i].reload_stack_mode = -2;
- + }
- + }
- + }
- + if (!spill_candidate[REGNO (pat)].first_set_to_reload)
- + {
- + spill_candidate[REGNO (pat)].disregard = 1;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == REGNO (pat))
- + {
- + reload_slots[i].reload_stack_mode = -2;
- + }
- + }
- + }
- + }
- + return;
- +
- + /* These codes have no constituent expressions
- + and are unique. */
- + case SCRATCH:
- + case CC0:
- + case PC:
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + return;
- +
- +
- + }
- + /* The reload stack slot must always be accessed in the same mode */
- + if ((GET_CODE (pat) == MEM || GET_CODE (pat) == SUBREG)
- + && is_a_reload_stack_slot (pat, &indx, 0, 0))
- + {
- + if (GET_CODE (pat) == SUBREG)
- + {
- + /* Signal invalid */
- + reload_slots[indx].reload_stack_mode = -2;
- + }
- + else if (reload_slots[indx].reload_stack_mode == -1)
- + {
- + reload_slots[indx].reload_stack_mode = GET_MODE (pat);
- + }
- + else if (reload_slots[indx].reload_stack_mode != GET_MODE (pat))
- + {
- + /* Signal invalid */
- + reload_slots[indx].reload_stack_mode = -2;
- + }
- + }
- + fmt = GET_RTX_FORMAT (code);
- +
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + {
- + if (fmt[i] == 'E')
- + {
- + register int j;
- + for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
- + spill_handle_regs_mentioned (XVECEXP (pat, i, j));
- + }
- + else if (fmt[i] == 'e')
- + spill_handle_regs_mentioned (XEXP (pat, i));
- + }
- + }
- +
- +
- + /*
- + Return 1 if insn updates a value by a constant value */
- + static
- + int
- + is_updated_by_const (insn)
- + rtx insn;
- + {
- + if (GET_CODE (PATTERN (insn)) != SET)
- + {
- + return (0);
- + }
- + if (GET_RTX_LENGTH (GET_CODE (SET_SRC (PATTERN (insn)))) != 2)
- + {
- + return (0);
- + }
- + if (!rtx_equal_p (XEXP (SET_SRC (PATTERN (insn)), 0),
- + SET_DEST (PATTERN (insn))))
- + {
- + return (0);
- + }
- + if (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) != CONST_INT)
- + {
- + return (0);
- + }
- + return (1);
- + }
- +
- +
- + /*
- + Return 1 if insn updates a value by a constant value or register */
- + static
- + int
- + is_updated_by_const_or_reg (insn)
- + rtx insn;
- + {
- + if (GET_CODE (PATTERN (insn)) != SET)
- + {
- + return (0);
- + }
- + if (GET_RTX_LENGTH (GET_CODE (SET_SRC (PATTERN (insn)))) != 2)
- + {
- + return (0);
- + }
- + if (!rtx_equal_p (XEXP (SET_SRC (PATTERN (insn)), 0),
- + SET_DEST (PATTERN (insn))))
- + {
- + return (0);
- + }
- + if (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) != CONST_INT
- + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) != REG)
- + {
- + return (0);
- + }
- + return (1);
- + }
- +
- +
- + /* Go over the whole function and do
- +
- + spill_slotA <- regY spill_slotA <- regY
- + . sequence of code not . sequence of code not
- + . affecting regY or => . affecting regY or
- + . spill_slotA . spill_slotA
- + regX <- spill_slotA regX <- regY
- + */
- + void
- + peep_spills (f, dumpfile)
- + rtx f;
- + FILE * dumpfile;
- + {
- + rtx insn, next, note;
- + int i, indx, insn_code_number, success;
- +
- + undobuf.num_undo = 0;
- + num_reload_stack_slots = 0;
- + cur_stack_offset = 0;
- + bzero (spill_candidate, FIRST_PSEUDO_REGISTER * sizeof (spill_candidate[0]));
- + loop_dump_stream = dumpfile;
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "\n\nDoing peep spills\n\n");
- + }
- + insn = f;
- + while (insn)
- + {
- + if (GET_CODE (insn) == INSN && RTX_IS_SPILL_P (insn)
- + && GET_CODE (SET_SRC (PATTERN (insn))) == MEM
- + && is_a_stack_slot (SET_SRC (PATTERN (insn)))
- + && !is_a_reload_stack_slot (SET_SRC (PATTERN (insn)), &indx,
- + cur_stack_offset, 0) )
- + {
- + if (num_reload_stack_slots >= MAX_RELOAD_STACK_SLOTS)
- + {
- + return;
- + }
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "reload slot at insn %d offset %d %d %d\n",
- + INSN_UID (insn), cur_stack_offset,
- + RTX_IS_SPILL_P (SET_SRC (PATTERN (insn))),
- + RTX_IS_SPILL_P (XEXP (SET_SRC (PATTERN (insn)), 0)));
- + }
- + reload_slots[num_reload_stack_slots].is_loaded_to_reg = -1;
- + reload_slots[num_reload_stack_slots].last_store = NULL;
- + reload_slots[num_reload_stack_slots].cur_stack_offset
- + = cur_stack_offset;
- + reload_slots[num_reload_stack_slots].reload_stack_slot
- + = SET_SRC (PATTERN (insn));
- + reload_slots[num_reload_stack_slots++].reload_insn = insn;
- + }
- + else if (GET_CODE (insn) == INSN && RTX_IS_SPILL_P (insn)
- + && GET_CODE (SET_DEST (PATTERN (insn))) == MEM
- + && is_a_stack_slot (SET_DEST (PATTERN (insn)))
- + && !is_a_reload_stack_slot (SET_DEST (PATTERN (insn)), &indx,
- + cur_stack_offset, 0) )
- + {
- + if (num_reload_stack_slots >= MAX_RELOAD_STACK_SLOTS)
- + {
- + return;
- + }
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "reload slot at insn %d offset %d\n",
- + INSN_UID (insn), cur_stack_offset);
- + }
- + reload_slots[num_reload_stack_slots].is_loaded_to_reg = -1;
- + reload_slots[num_reload_stack_slots].last_store = NULL;
- + reload_slots[num_reload_stack_slots].cur_stack_offset
- + = cur_stack_offset;
- + reload_slots[num_reload_stack_slots].reload_stack_slot
- + = SET_DEST (PATTERN (insn));
- + reload_slots[num_reload_stack_slots++].reload_insn = insn;
- + }
- + if (GET_CODE (insn) == INSN)
- + {
- + if (GET_CODE (PATTERN (insn)) == SET)
- + update_stack_offset (PATTERN (insn), &cur_stack_offset);
- + else if (GET_CODE (PATTERN (insn)) == PARALLEL)
- + {
- + for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- + update_stack_offset (XVECEXP (PATTERN (insn), 0, i),
- + &cur_stack_offset);
- + }
- + }
- + insn = NEXT_INSN (insn);
- + }
- + cur_stack_offset = 0;
- + insn = f;
- + while (insn)
- + {
- + if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
- + {
- + spill_peep_insn (insn, PATTERN (insn));
- + if (have_flow_analysis
- + && GET_CODE (PATTERN (insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (insn))) == REG
- + && (next = next_nonnote_insn (insn))
- + && GET_CODE (next) == INSN
- + && GET_CODE (next) == INSN
- + && (note = find_regno_note (next,
- + REG_DEAD,
- + REGNO (SET_DEST (PATTERN (insn)))))
- + && rtx_equal_p (XEXP (note, 0), SET_DEST (PATTERN (insn)))
- + )
- + { /* we have reg1 <- reg2 and reg1 dead in next insn
- + replace reg1 with reg2 in next insn and delete this
- + insn */
- + init_undo_buf ();
- + subst_in_insn (next,
- + PATTERN (next),
- + SET_DEST (PATTERN (insn)),
- + SET_SRC (PATTERN (insn)),
- + 0,
- + 0);
- + if (reg_overlap_mentioned_p (XEXP (note, 0), PATTERN (next))
- + || (insn_code_number = recog (PATTERN (next), next, 0)) < 0)
- + {
- + loop_undo_all ();
- + success = 0;
- + }
- + else
- + {
- + success = 1;
- + #ifdef REGISTER_CONSTRAINTS
- + INSN_CODE (next) = insn_code_number;
- + insn_extract (next);
- + if (!constrain_operands (insn_code_number, 1))
- + {
- + loop_undo_all ();
- + INSN_CODE (next)
- + = recog (PATTERN (next),
- + next, 0);
- + success = 0;
- + }
- + #endif
- + if (success)
- + {
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream,
- + "replace reg %d with reg %d in insn %d, delete insn %d\n",
- + REGNO (SET_DEST (PATTERN (insn))),
- + REGNO (SET_SRC (PATTERN (insn))),
- + INSN_UID (next), INSN_UID (insn));
- + }
- + PUT_CODE (insn, NOTE);
- + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (insn) = 0;
- + remove_note (next, note);
- + }
- + }
- + }
- + }
- + else if (GET_CODE (insn) == CODE_LABEL)
- + {
- + peep_init_info ();
- + }
- + insn = NEXT_INSN (insn);
- + }
- + have_flow_analysis = 0;
- + }
- +
- + static
- + void
- + peep_init_info ()
- + {
- + int i;
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + spill_candidate[i].reload_slot = 0;
- + spill_candidate[i].disregard = 0;
- + }
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + reload_slots[i].is_loaded_to_reg = -1;
- + reload_slots[i].last_store = NULL;
- + }
- + }
- +
- +
- + /*
- + In body of insn replace any reload stack slots with registers that
- + have the same value
- + */
- + static
- + void
- + spill_peep_insn (insn, body)
- + rtx insn;
- + rtx body;
- + {
- + enum rtx_code code;
- + int i, j, indx, regno, cand_num, insn_code_number, cur_code_number, success,
- + n_regs;
- +
- + undobuf.num_undo = 0;
- + code = GET_CODE (body);
- +
- + if (code == SET)
- + {
- +
- + if (/*cur_stack_offset == 0*/ 1)
- + {
- + if (GET_CODE (SET_SRC (body)) == MEM
- + && is_a_reload_stack_slot (SET_SRC (body), &indx, cur_stack_offset, 0))
- + {
- + cand_num = reload_slots[indx].is_loaded_to_reg;
- + if (cand_num != -1 && spill_candidate[cand_num].disregard == 0
- + && spill_candidate[cand_num].reload_slot
- + && GET_MODE (spill_candidate[cand_num].reload_slot)
- + == GET_MODE (SET_SRC (body))
- + && are_same_reload_slots (spill_candidate[cand_num].reload_slot,
- + spill_candidate[cand_num].cur_stack_offset,
- + SET_SRC (body), cur_stack_offset))
- + {
- + SET_SRC (body) = spill_candidate[cand_num].hard_reg;
- + if ((insn_code_number = recog (PATTERN (insn), insn, 0)) < 0)
- + {
- + SET_SRC (body) = spill_candidate[cand_num].reload_slot;
- + }
- + else
- + {
- + success = 1;
- + #ifdef REGISTER_CONSTRAINTS
- + INSN_CODE (insn) = insn_code_number;
- + insn_extract (insn);
- + if (!constrain_operands (insn_code_number, 1))
- + {
- + SET_SRC (body)
- + = spill_candidate[cand_num].reload_slot;
- + INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
- + success = 0;
- + }
- + #endif
- + if (success && loop_dump_stream)
- + {
- + fprintf (loop_dump_stream,
- + " replacing stack slot (src) with reg%d in insn %d\n",
- + REGNO (spill_candidate[cand_num].hard_reg), INSN_UID (insn));
- + }
- + }
- + }
- + }
- + else
- + {
- + undobuf.storage = (char *) oballoc (0);
- + replace_spill_slots (insn, SET_SRC (body), &SET_SRC (body));
- + if (undobuf.num_undo)
- + {
- + if ((insn_code_number = recog (PATTERN (insn), insn, 0)) < 0)
- + {
- + loop_undo_all ();
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " replacment did not succeed %d\n", INSN_UID (insn));
- + }
- + }
- + #ifdef REGISTER_CONSTRAINTS
- + else
- + {
- + INSN_CODE (insn) = insn_code_number;
- + insn_extract (insn);
- + if (!constrain_operands (insn_code_number, 1))
- + {
- + loop_undo_all ();
- + INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " replacment did not succeed %d\n", INSN_UID (insn));
- + }
- + }
- + }
- + #endif
- + undobuf.num_undo = 0;
- + }
- + }
- + }
- + if (GET_CODE (SET_DEST (body)) == REG
- + && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER)
- + {
- + regno = REGNO (SET_DEST (body));
- + if (HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body))) > 1)
- + {
- + regno = REGNO (SET_DEST (body));
- + n_regs = HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body)));
- + for (j = 0; j < n_regs; j++)
- + {
- + spill_candidate[regno + j].disregard = 1;
- + spill_candidate[regno + j].reload_slot = NULL;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == regno + i)
- + {
- + reload_slots[i].is_loaded_to_reg = -1;
- + }
- + }
- + }
- + }
- + if (GET_CODE (SET_SRC (body)) == MEM
- + && is_a_reload_stack_slot (SET_SRC (body), &indx, cur_stack_offset, 0)
- + && HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body))) == 1)
- + { /* It sets it to the value in a reload stack slot */
- + spill_candidate[regno].reload_slot = SET_SRC (body);
- + spill_candidate[regno].hard_reg = SET_DEST (body);
- + spill_candidate[regno].disregard = 0;
- + spill_candidate[regno].reload_insn = insn;
- + spill_candidate[regno].cur_stack_offset = cur_stack_offset;
- + reload_slots[indx].last_store = NULL;
- + reload_slots[indx].is_loaded_to_reg = regno;
- + }
- + else
- + {
- + spill_candidate[regno].disregard = 1;
- + spill_candidate[regno].reload_slot = NULL;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == regno)
- + {
- + reload_slots[i].is_loaded_to_reg = -1;
- + }
- + }
- + }
- + }
- + else if (GET_CODE (SET_DEST (body)) == SUBREG
- + && GET_CODE (SUBREG_REG (SET_DEST (body))) == REG
- + && REGNO (SUBREG_REG (SET_DEST (body))) < FIRST_PSEUDO_REGISTER)
- + { /* Simple handling of subregs - invalidate the subreg being set */
- + regno = REGNO (SUBREG_REG (SET_DEST (body)));
- + n_regs = HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body)));
- + for (j = 0; j < n_regs; j++)
- + {
- + spill_candidate[regno + j].disregard = 1;
- + spill_candidate[regno + j].reload_slot = NULL;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == regno + i)
- + {
- + reload_slots[i].is_loaded_to_reg = -1;
- + }
- + }
- + }
- + }
- + else if (is_a_reload_stack_slot (SET_DEST (body), &indx, cur_stack_offset, 0))
- + { /* This is an update of a reload_stack_slot */
- + /* Check if last write into this reload slot can be deleted */
- + if (reload_slots[indx].last_store
- + && GET_CODE (SET_DEST (body)) != SUBREG
- + /* && GET_CODE (SET_SRC (body)) == REG */
- + && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
- + && GET_MODE (SET_DEST ( PATTERN (reload_slots[indx].last_store)))
- + == GET_MODE (SET_DEST (body))
- + && spill_slot_unused_between (
- + SET_DEST ( PATTERN (reload_slots[indx].last_store)),
- + reload_slots[indx].last_store, insn))
- + {
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "delete redundant spill store at %d becuase of re-store at %d\n",
- + INSN_UID (reload_slots[indx].last_store),
- + INSN_UID (insn));
- + }
- + PUT_CODE (reload_slots[indx].last_store, NOTE);
- + NOTE_LINE_NUMBER (reload_slots[indx].last_store) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (reload_slots[indx].last_store) = 0;
- + reload_slots[indx].is_loaded_to_reg = -1;
- + reload_slots[indx].last_store = NULL;
- + }
- + if (GET_CODE (SET_SRC (body)) == REG
- + && GET_CODE (SET_DEST (body)) != SUBREG
- + &&HARD_REGNO_NREGS(REGNO(SET_SRC(body)),
- + GET_MODE(SET_DEST(body))) == 1
- + && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER)
- + {
- + regno = REGNO (SET_SRC (body));
- + spill_candidate[regno].reload_slot = SET_DEST (body);
- + spill_candidate[regno].hard_reg = SET_SRC (body);
- + spill_candidate[regno].disregard = 0;
- + spill_candidate[regno].reload_insn = insn;
- + spill_candidate[regno].cur_stack_offset = cur_stack_offset;
- + reload_slots[indx].last_store = insn;
- + reload_slots[indx].is_loaded_to_reg = regno;
- + }
- + else
- + {
- + regno = reload_slots[indx].is_loaded_to_reg;
- + if (regno != -1)
- + { /* This candidate is now invalid */
- + spill_candidate[regno].disregard = 1;
- + spill_candidate[regno].reload_slot = NULL;
- + }
- + reload_slots[indx].is_loaded_to_reg = -1;
- + reload_slots[indx].last_store = NULL;
- + }
- + }
- + update_stack_offset (body, &cur_stack_offset);
- + }
- + else if (code == CLOBBER)
- + {
- + if (GET_CODE (SET_DEST (body)) == REG
- + && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER)
- + {
- + regno = REGNO (SET_DEST (body));
- + n_regs = HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body)));
- + for (j = 0; j < n_regs; j++)
- + {
- + spill_candidate[regno + j].disregard = 1;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == (regno + j))
- + {
- + reload_slots[i].is_loaded_to_reg = -1;
- + }
- + }
- + }
- + }
- + else if (GET_CODE (SET_DEST (body)) == SUBREG
- + && GET_CODE (SUBREG_REG (SET_DEST (body))) == REG
- + && REGNO (SUBREG_REG (SET_DEST (body))) < FIRST_PSEUDO_REGISTER)
- + {
- + regno = REGNO (SUBREG_REG (SET_DEST (body)));
- + n_regs
- + = max (HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (body))),
- + HARD_REGNO_NREGS (regno,
- + GET_MODE (SUBREG_REG (SET_DEST (body)))));
- + for (j = 0; j < n_regs; j++)
- + {
- + spill_candidate[regno + j].disregard = 1;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == (regno + j))
- + {
- + reload_slots[i].is_loaded_to_reg = -1;
- + }
- + }
- + }
- + }
- + else if (is_a_reload_stack_slot (SET_DEST (body), &indx, cur_stack_offset, 0))
- + {
- + regno = reload_slots[indx].is_loaded_to_reg;
- + if (regno != -1)
- + { /* This candidate is now invalid */
- + spill_candidate[regno].disregard = 1;
- + spill_candidate[regno].reload_slot = NULL;
- + }
- + reload_slots[indx].is_loaded_to_reg = -1;
- + reload_slots[indx].last_store = NULL;
- + }
- + }
- + if (code == PARALLEL)
- + {
- + for (i = 0; i < XVECLEN (body, 0); i++)
- + spill_peep_insn (insn, XVECEXP (body, 0, i));
- + }
- + if (GET_CODE (insn) == CALL_INSN)
- + { /* All call clobbered registers are no longer valid */
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + if (call_used_regs[i])
- + {
- + spill_candidate[i].disregard = 1;
- + for (j=0; j < num_reload_stack_slots; j++)
- + {
- + if (reload_slots[j].is_loaded_to_reg == i)
- + {
- + reload_slots[j].is_loaded_to_reg = -1;
- + }
- + }
- + }
- + }
- + }
- + }
- +
- + /*
- + Return 1 iff we are sure that the spill_slot (or any subpart of it)
- + is not refernced between start and end. Also there must be no
- + CALL JUMP or LABELs in between them
- + */
- + static
- + int
- + spill_slot_unused_between (spill_slot, start, end)
- + rtx spill_slot, start, end;
- + {
- + rtx tinsn;
- + int mcur_stack_offset = 0;
- +
- + for (tinsn = next_nonnote_insn (start);
- + tinsn && tinsn != end;
- + tinsn = next_nonnote_insn (tinsn))
- + {
- + if (GET_CODE (tinsn) == CALL_INSN || GET_CODE (tinsn) == JUMP_INSN
- + || GET_CODE (tinsn) == CODE_LABEL)
- + {
- + return (0);
- + }
- + if (spill_slot_mentioned(spill_slot, PATTERN (tinsn), mcur_stack_offset))
- + {
- + return (0);
- + }
- + update_stack_offset (PATTERN (tinsn), &mcur_stack_offset);
- + }
- + return (1);
- + }
- +
- + /*
- + Return 1 if spill_slot or any part of it is mentioned in pat.
- + relative_stack_offset is the offset of the stack pointer relative
- + to the point at which spill_slot was stored into.
- + */
- +
- + static int
- + spill_slot_mentioned (spill_slot, pat, relative_stack_offset)
- + rtx pat, spill_slot;
- + int relative_stack_offset;
- + {
- + register char *fmt;
- + register int i;
- + register enum rtx_code code;
- +
- + code = GET_CODE (pat);
- +
- + switch (code)
- + {
- + /* These codes have no constituent expressions
- + and are unique. */
- + case REG:
- + case SCRATCH:
- + case CC0:
- + case PC:
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + return (0);
- +
- + case MEM:
- + if (is_a_stack_slot (pat)
- + && are_same_reload_slots (spill_slot, 0, pat, relative_stack_offset))
- + {
- + return (1);
- + }
- + return (0);
- +
- + }
- +
- +
- + fmt = GET_RTX_FORMAT (code);
- +
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + {
- + if (fmt[i] == 'E')
- + {
- + register int j;
- + for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
- + if (spill_slot_mentioned (spill_slot, XVECEXP (pat, i, j),
- + relative_stack_offset))
- + {
- + return (1);
- + }
- + }
- + else if (fmt[i] == 'e')
- + if (spill_slot_mentioned (spill_slot, XEXP (pat, i),
- + relative_stack_offset))
- + {
- + return (1);
- + }
- + }
- + return (0);
- + }
- +
- +
- + /*
- + Keep track of the depth of the stack
- + */
- + /* static */
- + void
- + update_stack_offset (pat, addr_stack_offset)
- + rtx pat;
- + int *addr_stack_offset;
- + {
- + int i;
- + if (GET_CODE (pat) != SET)
- + {
- + return;
- + }
- + if (GET_CODE (SET_DEST (pat)) == REG
- + && XINT (SET_DEST (pat), 0) == STACK_POINTER_REGNUM
- + && GET_CODE (SET_SRC (pat)) == PLUS
- + && GET_CODE (XEXP (SET_SRC (pat), 0)) == REG
- + && XINT (XEXP (SET_SRC (pat), 0), 0) == STACK_POINTER_REGNUM)
- + {
- + *addr_stack_offset -= XINT (XEXP (SET_SRC (pat), 1), 0);
- + }
- + else if (GET_CODE (SET_DEST (pat)) == MEM
- + && GET_CODE (XEXP (SET_DEST (pat), 0)) == PRE_DEC
- + && XEXP (XEXP (SET_DEST (pat), 0), 0) == stack_pointer_rtx)
- + {
- + spill_candidate[STACK_POINTER_REGNUM].disregard = 1;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == STACK_POINTER_REGNUM)
- + {
- + reload_slots[i].is_loaded_to_reg = -1;
- + }
- + }
- + *addr_stack_offset += GET_MODE_SIZE (GET_MODE (SET_DEST (pat)));
- + }
- + else if (GET_CODE (SET_DEST (pat)) == MEM
- + && GET_CODE (XEXP (SET_DEST (pat), 0)) == PRE_INC
- + && XEXP (XEXP (SET_DEST (pat), 0), 0) == stack_pointer_rtx)
- + {
- + spill_candidate[STACK_POINTER_REGNUM].disregard = 1;
- + for (i=0; i < num_reload_stack_slots; i++)
- + {
- + if (reload_slots[i].is_loaded_to_reg == STACK_POINTER_REGNUM)
- + {
- + reload_slots[i].is_loaded_to_reg = -1;
- + }
- + }
- + *addr_stack_offset -= GET_MODE_SIZE (GET_MODE (SET_DEST (pat)));
- + }
- + }
- +
- +
- + /*
- + Replace stack spill slots in pat of insn with the appropriate spill
- + candidate
- + */
- + static
- + void
- + replace_spill_slots (insn, pat, where)
- + rtx insn;
- + rtx pat;
- + rtx *where;
- + {
- + register RTX_CODE code = GET_CODE (pat);
- + register int i, j;
- + register char *fmt;
- + int cand_num, indx;
- + rtx note;
- +
- + switch (code)
- + {
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + case REG:
- + return;
- +
- + default:
- + break;
- + }
- + if (GET_CODE (pat) == MEM && is_a_reload_stack_slot (pat, &indx, cur_stack_offset, 0))
- + {
- + cand_num = reload_slots[indx].is_loaded_to_reg;
- + if (cand_num != -1 && spill_candidate[cand_num].disregard == 0
- + && spill_candidate[cand_num].reload_slot
- + && GET_MODE (spill_candidate[cand_num].reload_slot)
- + == GET_MODE (pat)
- + && are_same_reload_slots (spill_candidate[cand_num].reload_slot,
- + spill_candidate[cand_num].cur_stack_offset,
- + pat, cur_stack_offset))
- + {
- + note = find_reg_note (spill_candidate[cand_num].reload_insn,
- + REG_DEAD,
- + spill_candidate[cand_num].hard_reg);
- + if (note)
- + {
- + remove_note (spill_candidate[cand_num].reload_insn, note);
- + }
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " replacing stack slot with reg%d in insn %d\n",
- + REGNO (spill_candidate[cand_num].hard_reg), INSN_UID (insn));
- + }
- + LOOP_SUBST (where, spill_candidate[cand_num].hard_reg);
- + }
- + }
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + replace_spill_slots (insn, XEXP (pat, i), &XEXP (pat, i));
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + replace_spill_slots (insn, XVECEXP (pat, i, j), &XVECEXP (pat, i, j));
- + }
- + }
- +
- + /*
- + Replace any hard registers in pat of insn, that are on a linked
- + list of spill candidates, with the head candidate of the list
- + */
- + static
- + rtx
- + replace_linked_regs (insn, pat)
- + rtx insn;
- + rtx pat;
- + {
- + register RTX_CODE code = GET_CODE (pat);
- + register int i, j;
- + register char *fmt;
- + int cand_num, indx;
- + rtx note;
- +
- + switch (code)
- + {
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + return pat;
- +
- + case REG:
- + if (spill_candidate[REGNO (pat)].head_cand
- + && (spill_candidate[REGNO (pat)].head_cand)->disregard == 0)
- + {
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " replacing reg%d with reg%d in insn %d\n",
- + REGNO (pat),
- + REGNO ((spill_candidate[REGNO (pat)].head_cand)->hard_reg),
- + INSN_UID (insn));
- + }
- + return ((spill_candidate[REGNO (pat)].head_cand)->hard_reg);
- + }
- + else
- + return pat;
- +
- + default:
- + break;
- + }
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + XEXP (pat, i) = replace_linked_regs (insn, XEXP (pat, i));
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + XVECEXP (pat, i, j)
- + = replace_linked_regs (insn, XVECEXP (pat, i, j));
- + }
- + return pat;
- + }
- +
- +
- + /*
- + Mark all registers mentioned in insns between loop_start and loop_end
- + and that are also mentioned outside of the loop
- + */
- + static void
- + mark_regs_live_outside (loop_start, loop_end)
- + rtx loop_start;
- + rtx loop_end;
- + {
- + rtx insn;
- + int in_loop = 0;
- +
- + insn = get_insns ();
- + while (insn)
- + {
- + if (insn == loop_start)
- + {
- + in_loop = 1;
- + }
- + else if (insn == loop_end)
- + {
- + in_loop = 0;
- + }
- + else if (in_loop == 0
- + && (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
- + || GET_CODE (insn) == JUMP_INSN))
- + {
- + mark_regs_mentioned (PATTERN (insn), insn);
- + }
- + insn = NEXT_INSN (insn);
- + }
- + }
- +
- +
- + /*
- + Each register mentioned in pat, except for the destination register of
- + the insn, is marked as reg_live_outside_loop
- + */
- + static void
- + mark_regs_mentioned (pat, insn)
- + rtx pat, insn;
- + {
- + register char *fmt;
- + register int i;
- + register enum rtx_code code;
- +
- + if (GET_CODE (pat) == SET
- + && GET_CODE (SET_DEST (pat)) == REG && is_a_param_slot (SET_SRC (pat)))
- + {
- + return;
- + }
- +
- + code = GET_CODE (pat);
- +
- + switch (code)
- + {
- + case REG:
- + if (REGNO (pat) < max_reg_before_loop)
- + {
- + reg_live_outside_loop[REGNO (pat)] = 1;
- + }
- + return;
- +
- + /* These codes have no constituent expressions
- + and are unique. */
- + case SCRATCH:
- + case CC0:
- + case PC:
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + return;
- +
- +
- + }
- +
- +
- + fmt = GET_RTX_FORMAT (code);
- +
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + {
- + if (fmt[i] == 'E')
- + {
- + register int j;
- + for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
- + mark_regs_mentioned (XVECEXP (pat, i, j), insn);
- + }
- + else if (fmt[i] == 'e')
- + mark_regs_mentioned (XEXP (pat, i), insn);
- + }
- + }
- +
- + /* Return 1 iff there is a loop_begin note between loop_start and loop_end
- + otherwise return 0 */
- +
- + static int
- + loop_contains_loop (loop_start, loop_end)
- + rtx loop_start;
- + rtx loop_end;
- + {
- + rtx insn;
- +
- + insn = NEXT_INSN (loop_start);
- + while (insn && insn != loop_end)
- + {
- + if (GET_CODE (insn) == NOTE
- + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- + {
- + return (1);
- + }
- + insn = NEXT_INSN (insn);
- + }
- + return (0);
- + }
- +
- +
- + /* reload_slots[indx] is a reload slot that was never updated in loop
- + but could not be lifted only because the register it is
- + loaded into was also set to something else in loop.
- + Lets see if the reload slot was set in the basic block
- + just prior to the loop by some inexpensive operation.
- + (particularly a move from memory into a register and
- + a move of that register onto stack). If so lets
- + replace each load of the reload slot in the loop with
- + a load of the memory and delete the code that loaded
- + and spilled it outside the loop.
- + This corrects the preloading of loop invariants that
- + could not be held in registers over the loop
- + */
- + static
- + void
- + push_load_into_loop (loop_start, loop_end, indx)
- + rtx loop_start;
- + rtx loop_end;
- + int indx;
- + {
- + rtx insn, insn_sets_reload_slot, val_in_reload_slot, insns_deleted[2],
- + update_log_links_start, rn, prev, link;
- + int rindx, i, found_set, num_deleted;
- +
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "\nTry to push load of pseudo %d into loop\n",
- + reload_slots[indx].stack_slot_pseudo_reg);
- + }
- + /* Look for insn before the loop that sets this reload slot */
- + insn = PREV_INSN (loop_start);
- + insn_sets_reload_slot = 0;
- + while (insn && !insn_sets_reload_slot)
- + {
- + if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
- + || GET_CODE (insn) == CODE_LABEL
- + || (GET_CODE (insn) == NOTE
- + && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
- + || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
- + )
- + )
- + || (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) != SET))
- + {
- + break;
- + }
- + else if (GET_CODE (insn) == INSN
- + && rtx_equal_p (SET_DEST (PATTERN (insn)), reload_slots[indx].reload_stack_slot))
- + {
- + insn_sets_reload_slot = insn;
- + }
- + insn = PREV_INSN (insn);
- + }
- + if (!insn_sets_reload_slot)
- + {
- + return;
- + }
- + /* Now see if the source is a register and that register is
- + set by the immediately preceeding insn - then source of
- + the immediately preceeding insn is the value in the reload
- + slot throughout the loop */
- + if (GET_CODE (SET_SRC (PATTERN (insn_sets_reload_slot))) == REG
- + && GET_CODE (PREV_INSN (insn_sets_reload_slot)) == INSN
- + && GET_CODE (PATTERN (PREV_INSN (insn_sets_reload_slot))) == SET
- + && rtx_equal_p (SET_DEST (PATTERN (PREV_INSN (insn_sets_reload_slot))),
- + SET_SRC (PATTERN (insn_sets_reload_slot))))
- + {
- + val_in_reload_slot = SET_SRC (PATTERN (PREV_INSN (insn_sets_reload_slot)));
- + }
- + else
- + {
- + return;
- + }
- + if (is_a_reload_stack_slot (val_in_reload_slot, &rindx, cur_stack_offset, 0))
- + { /* Don't want to handle these */
- + return;
- + }
- + /* Now make sure that this value is not changed in loop */
- + if (GET_CODE (val_in_reload_slot) != MEM || !invariant_p (val_in_reload_slot))
- + {
- + return;
- + }
- + for (i = loop_store_mems_idx - 1; i >= 0; i--)
- + {
- + if (true_dependence (loop_store_mems[i], val_in_reload_slot)
- + && !is_a_reload_stack_slot (loop_store_mems[i], &rindx, cur_stack_offset, 0)
- + )
- + {
- + return;
- + }
- + }
- + /* Now we know that the value can be substituted and that the store into
- + the reload slot outside the loop (i.e. insn_sets_reload_slot)
- + can be deleted.
- + we also want to delete the load of the reload slot
- + (i.e PREV_INSN(insn_sets_reload_slot)). we can do this if the register
- + loaded (i.e. SET_DEST(PATTERN(PREV_INSN(insn_sets_reload_slot))) is
- + set before used after PREV_INSN(insn_sets_reload_slot))
- + */
- + insn = NEXT_INSN (insn_sets_reload_slot);
- + found_set = 0;
- + while (!found_set && insn && insn != loop_end)
- + {
- + if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
- + || (GET_CODE (insn) == CODE_LABEL && PREV_INSN (insn) != loop_start))
- + {
- + break;
- + }
- + if (GET_CODE (insn) == INSN)
- + {
- + if (reg_overlap_mentioned_p (
- + SET_DEST (PATTERN (PREV_INSN (insn_sets_reload_slot))),
- + PATTERN (insn)))
- + {
- + break;
- + }
- + if (GET_CODE (PATTERN (insn)) == SET
- + && rtx_equal_p (SET_DEST (PATTERN (insn)),
- + SET_DEST (PATTERN (PREV_INSN (insn_sets_reload_slot)))))
- + {
- + found_set = 1;
- + }
- + }
- + insn = NEXT_INSN (insn);
- + }
- + /* Do the replacement throughout the loop */
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "replacing reload slot %d with: throughout loop\n",
- + indx);
- + tdebug_rtx (val_in_reload_slot, loop_dump_stream);
- + }
- + insn = NEXT_INSN (insn_sets_reload_slot);
- + while (insn != loop_end)
- + {
- + if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
- + || GET_CODE (insn) == JUMP_INSN)
- + {
- + init_undo_buf ();
- + subst_in_insn (insn, PATTERN (insn),
- + reload_slots[indx].reload_stack_slot,
- + val_in_reload_slot, 1, 0);
- +
- + }
- + insn = NEXT_INSN (insn);
- + }
- + insns_deleted[0] = NULL;
- + insns_deleted[1] = NULL;
- + num_deleted = 0;
- + update_log_links_start = PREV_INSN (insn_sets_reload_slot);
- + if (found_set)
- + {
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " delete insn %d\n",
- + INSN_UID (PREV_INSN (insn_sets_reload_slot)));
- + }
- + insns_deleted[num_deleted++] = PREV_INSN (insn_sets_reload_slot);
- + delete_insn (PREV_INSN (insn_sets_reload_slot));
- + }
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, " delete insn %d\n",
- + INSN_UID (insn_sets_reload_slot));
- + }
- + insns_deleted[num_deleted++] = insn_sets_reload_slot;
- + delete_insn (insn_sets_reload_slot);
- + /* Remove these deleted insns from any log links they are on */
- + for (rn = update_log_links_start; rn != loop_start; rn = NEXT_INSN (rn))
- + {
- + if ((GET_CODE (rn) == INSN || GET_CODE (rn) == JUMP_INSN
- + || GET_CODE (rn) == CALL_INSN) && LOG_LINKS (rn))
- + {
- + for (prev = 0, link = LOG_LINKS (rn); link;
- + prev = link, link = XEXP (link, 1))
- + {
- + if (XEXP (link, 0) == insns_deleted[0]
- + || (num_deleted == 2 && XEXP (link, 0) == insns_deleted[1]))
- + {
- + if (prev)
- + XEXP (prev, 1) = XEXP (link, 1);
- + else
- + LOG_LINKS (rn) = XEXP (link, 1);
- + }
- + }
- + }
- + }
- + }
- +
- + void
- + init_undo_buf ()
- + {
- + undobuf.storage = (char *) oballoc (0);
- + undobuf.num_undo = 0;
- + }
- +
- + /* In pat of insn replace org with new. If not_dest is 1 then
- + don't do the rplacement if org is ae destination of a SET
- + */
- + void
- + subst_in_insn (insn, pat, org, new, not_dest, is_dest)
- + rtx insn, pat, org, new;
- + int not_dest;
- + int is_dest;
- + {
- + inner_subst_in_insn (insn, pat, &pat, org, new, not_dest, is_dest);
- + }
- +
- + /* In pat of insn replace org with new. If not_dest is 1 then
- + don't do the rplacement if org is ae destination of a SET
- + */
- + static void
- + inner_subst_in_insn (insn, pat, where, org, new, not_dest, is_dest)
- + rtx insn, pat, org, new, *where;
- + int not_dest;
- + int is_dest;
- + {
- + register RTX_CODE code = GET_CODE (pat);
- + register int i, j;
- + register char *fmt;
- +
- + if (not_dest && is_dest)
- + {
- + return;
- + }
- + switch (code)
- + {
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + return ;
- +
- +
- + }
- +
- + if (rtx_equal_p (pat, org))
- + {
- + LOOP_SUBST (where, new);
- + return;
- + }
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + {
- + if (not_dest && code == SET && i == 0)
- + is_dest = 1;
- + else
- + is_dest = 0;
- + if( XEXP (pat, i))
- + inner_subst_in_insn (insn, XEXP (pat, i), &XEXP (pat, i), org, new, not_dest, is_dest);
- + }
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + inner_subst_in_insn (insn, XVECEXP (pat, i, j), &XVECEXP (pat, i, j), org, new, not_dest, 0);
- + }
- + }
- +
- +
- + /* tsl - begin */
- +
- + /* Indexed by i, each entry indicates the last memory, register i was loaded
- + with, in the current loop (NULL if no reload until now) */
- +
- + static rtx last_reloads[FIRST_PSEUDO_REGISTER];
- +
- + #define LAST_RELOAD(REGNO) last_reloads[(REGNO)]
- +
- + /* If entry > 0 then the higher it is the less recently used it is.
- + If entry == 0 then that register number has not been used as reload
- + since last lable.
- + */
- +
- + static int reload_priority[FIRST_PSEUDO_REGISTER];
- +
- + /* Set of registers that are free and ready to be used at this moment. */
- +
- + extern HARD_REG_SET free_regs;
- +
- + extern void update_free_regs (rtx);
- + extern int find_free_reg (enum machine_mode);
- + static int find_last_reload (rtx);
- +
- + /* Replaces the reload registers of reload insns as follows:
- +
- + for each insn which loads memory into a register,
- + if the reload register is loaded with a memory, which was previously
- + loaded, and the reload register dies in the next insn, we
- + replace the reload register, with that already loaded with the stack slot
- + (assuming that register is free - we use the same free register scanning
- + method of the memory_simplify() function).
- + If the reload register was already used since the last label or call then
- + try to find a free register which was used less recently and replace the
- + reload register with the register found.
- + */
- +
- + void
- + replace_reload_registers (f, file)
- + rtx f;
- + FILE *file;
- + {
- + HARD_REG_SET saved_free_regs; /* for testing find_free_regs_between () */
- +
- + /* indicate wheter we are in a loop now */
- +
- + int in_loop_f = 0;
- + int save_code;
- + int i;
- +
- + /* make flow_analysis without changing the insns and saving the pseudo
- + registers information in basic_block_live_at_start */
- +
- + hard_reg_flow_analysis (f, file, 1 /* save pseudo register information */);
- + have_flow_analysis = 1;
- + bzero (last_reloads, sizeof last_reloads);
- +
- + if (n_basic_blocks > 0)
- + {
- + register int regno, block;
- +
- + /* To determine which registers are live after any insn, start from
- + the beginning of the basic block and scan insns, noting
- + which registers are set by each insn and which die there. */
- +
- + for (block = 0; block < n_basic_blocks; block++)
- + {
- + register rtx insn;
- + int end_of_block_f;
- +
- + if (file)
- + fprintf (file, "\nblock number: %d:\n", block);
- +
- + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- + /* at the beginning of a block, each non-live hard register is
- + considered free. */
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register int bit = 1 << (regno % REGSET_ELT_BITS);
- + if (basic_block_live_at_start[block][offset] & bit)
- + CLEAR_HARD_REG_BIT (free_regs, regno);
- + else
- + SET_HARD_REG_BIT (free_regs, regno);
- + }
- +
- + end_of_block_f = 0; /* signals the end of block reached */
- +
- + /* Traverse the block, an insn by insn. Maintain a history
- + of free registers and registers used to load memory
- + for use only in next insn (these are called reload_registers).
- + At CALLs and CODE_LABELs restart the history of reload_registers.
- + */
- +
- + for (insn = basic_block_head[block];
- + ! end_of_block_f;
- + insn = NEXT_INSN (insn))
- + {
- + rtx note, next, pat;
- + rtx loop_start; /* use to test find_free_regs_between () */
- + int regno;
- +
- + if (GET_CODE (insn) == CALL_INSN)
- + {
- + bzero (last_reloads, sizeof last_reloads);
- + bzero (reload_priority, sizeof reload_priority);
- + }
- + if (GET_CODE (insn) == CODE_LABEL)
- + {
- + bzero (last_reloads, sizeof last_reloads);
- + bzero (reload_priority, sizeof reload_priority);
- + loop_start = insn;
- + if (GET_CODE (PREV_INSN (insn)) == NOTE
- + && NOTE_LINE_NUMBER (PREV_INSN (insn))
- + == NOTE_INSN_LOOP_BEG)
- + {
- + in_loop_f = 1;
- + saved_free_regs = free_regs;
- + }
- + }
- + if (GET_CODE (insn) == JUMP_INSN
- + && GET_CODE (NEXT_INSN (insn)) == NOTE
- + && NOTE_LINE_NUMBER (NEXT_INSN (insn)) == NOTE_INSN_LOOP_END)
- + {
- + register int regno;
- + #if 0
- + if (in_loop_f)
- + {
- + find_free_regs_between (& saved_free_regs,
- + loop_start,
- + insn);
- + if (file)
- + {
- + fprintf (file,
- + "free regs found in loop (insns %d - %d): ",
- + INSN_UID (loop_start), INSN_UID (insn));
- + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- + if (TEST_HARD_REG_BIT (saved_free_regs, regno))
- + fprintf (file, "%d ", regno);
- + fprintf (file, "\n");
- + }
- + }
- + #endif
- + in_loop_f = 0;
- + }
- +
- + if (/*in_loop_f*/ 1)
- + {
- + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- + /*&& RTX_IS_SPILL_P (insn)*/
- + && (pat = PATTERN (insn))
- + && GET_CODE (pat) == SET
- + && GET_CODE (SET_DEST (pat)) == REG
- + && GET_CODE (SET_SRC (pat)) == MEM)
- + {
- + regno = REGNO (SET_DEST (pat));
- +
- + if ((next = next_nonnote_insn (insn))
- + && GET_CODE (next) == INSN
- + && (note = find_regno_note (next,
- + REG_DEAD,
- + regno)))
- + {
- + /* look for new_regno to replace with */
- + int new_regno = find_last_reload (SET_SRC (pat));
- + enum machine_mode mode = GET_MODE (SET_DEST (pat));
- +
- + /* tevid */
- + if (new_regno != FIRST_PSEUDO_REGISTER)
- + { /* The mode must be ok */
- + if (!HARD_REGNO_MODE_OK (new_regno, mode))
- + new_regno = FIRST_PSEUDO_REGISTER;
- + }
- + if (new_regno == FIRST_PSEUDO_REGISTER
- + || ! TEST_HARD_REG_BIT (free_regs, new_regno))
- + if (/*LAST_RELOAD (regno)*/
- + reload_priority[regno])
- + /* if we already used regno for reload in this
- + loop it is better to reload the new memory
- + to another register (if we find free one) */
- + {
- + new_regno = find_free_reg (mode);
- + if (reload_priority [new_regno] &&
- + reload_priority [regno] >=
- + reload_priority [new_regno])
- + {
- + new_regno = FIRST_PSEUDO_REGISTER;
- + }
- + }
- + else
- + /* this is the first time we're using this
- + register for reload in the current loop -
- + so we need no replacement */
- + new_regno = FIRST_PSEUDO_REGISTER;
- +
- +
- +
- +
- +
- + if (new_regno != FIRST_PSEUDO_REGISTER
- + /* if regno == new_regno no replcement needed */
- + && new_regno != regno)
- + {
- + register int nregs, i;
- + int stop_replacement = 0;
- +
- + rtx new_reg = gen_rtx (REG, mode, new_regno);
- + rtx old_reg = XEXP (note, 0);
- +
- + /* replace this register in the next insn */
- + init_undo_buf ();
- + subst_in_insn (next,
- + PATTERN (next),
- + old_reg,
- + new_reg,
- + 0,
- + 0);
- +
- + #ifdef REGISTER_CONSTRAINTS
- + save_code = INSN_CODE (next);
- +
- + if ((INSN_CODE (next) = recog (PATTERN (next),
- + next,
- + 0)) != -1)
- + insn_extract (next);
- +
- + if (INSN_CODE (next) == -1
- + || !constrain_operands (INSN_CODE (next), 1))
- + {
- + /* restore the previous situation */
- + INSN_CODE (next) = save_code;
- + loop_undo_all ();
- + /*subst_in_insn (next,
- + PATTERN (next),
- + new_reg,
- + old_reg,
- + 0,
- + 0);*/
- + stop_replacement = 1;
- + }
- + #endif
- + if (! stop_replacement)
- + {
- + rtx next_dest = SET_DEST (PATTERN (next));
- +
- + /* replace this insn's register with regno */
- + SET_DEST (pat) = new_reg;
- + #if 0
- + init_undo_buf ();
- + subst_in_insn (next,
- + note,
- + old_reg,
- + new_reg,
- + 0,
- + 0);
- + #endif
- +
- + /* The regno in the REG_DEAD note should be
- + changed */
- +
- + XEXP (note, 0) = new_reg;
- +
- + /* Now, if we replaced a REG_DEAD note, and
- + the new_reg is the destination of the next
- + insn, we should remove this note */
- + /* tevid replaced regno with new_regno,
- + twice */
- +
- + if (GET_CODE (next_dest) == REG
- + && REGNO (next_dest) == new_regno)
- + remove_death (new_regno, next);
- +
- + /* replace the registers in the free_register
- + list */
- + nregs = HARD_REGNO_NREGS (new_regno, mode);
- + for (i = 0; i < nregs; i++)
- + CLEAR_HARD_REG_BIT (free_regs, new_regno + i);
- + nregs = HARD_REGNO_NREGS (regno, mode);
- + for (i = 0; i < nregs; i++)
- + SET_HARD_REG_BIT (free_regs, regno + i);
- +
- + if (file)
- + {
- + fprintf (file, "insn %d: reload register",
- + INSN_UID (insn));
- + fprintf (file, " replaced (old %d new %d)\n",
- + regno, new_regno);
- + }
- + #ifdef REGISTER_CONSTRAINTS
- + } /* if (! stop_replacement) */
- + #endif
- +
- + } /* if (new_regno != FIRST_PSEUDO_REGISTER
- + && new_regno != regno) */
- +
- + else if (file)
- + {
- + fprintf (file, "insn %d: no free register for",
- + INSN_UID (insn));
- + fprintf (file, " reload replacement\n");
- + }
- + } /* if (next = next_nonnote (insn))
- + && (note = find_regno_note (next,
- + REG_DEAD,
- + regno))) */
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + if (reload_priority[i] > 0)
- + reload_priority[i]++;
- + reload_priority[REGNO (SET_DEST (PATTERN (insn)))] = 1;
- + } /* if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- + && RTX_IS_SPILL_P (insn)
- + && (pat = PATTERN (insn))
- + && GET_CODE (pat) == SET
- + && GET_CODE (SET_DEST (pat)) == REG */
- +
- + /* update the last_reloads array */
- +
- + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- + && (pat = PATTERN (insn))
- + && GET_CODE (pat) == SET
- + && GET_CODE (SET_DEST (pat)) == REG
- + && GET_CODE (SET_SRC (pat)) == MEM)
- + LAST_RELOAD (REGNO (SET_DEST (pat ))) = SET_SRC (pat);
- +
- + } /* if (in_loop_f) */
- +
- + end_of_block_f = (insn == basic_block_end[block]);
- +
- + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- + {
- + register int j;
- + rtx set;
- +
- + if (GET_CODE (insn) == CALL_INSN)
- + /* all call clobbered registers are now free */
- + for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
- + if (call_used_regs[j])
- + SET_HARD_REG_BIT (free_regs, j);
- +
- + update_free_regs (PATTERN (insn));
- +
- + /* Update LAST_RELOADs that are no longer valid */
- + update_last_reloads ( PATTERN (insn));
- +
- +
- + /* add each dead register to the free_regs set */
- + for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- + if ((REG_NOTE_KIND (note) == REG_DEAD
- + || REG_NOTE_KIND (note) == REG_UNUSED)
- + && GET_CODE (XEXP (note, 0)) == REG)
- + {
- + register int i;
- + register int regno = REGNO (XEXP (note, 0));
- + register int nregs =
- + HARD_REGNO_NREGS (regno, GET_MODE (XEXP (note, 0)));
- +
- + for (i = 0; i < nregs; i++)
- + SET_HARD_REG_BIT (free_regs, regno + i);
- + }
- + if ((note = find_reg_note (insn, REG_WAS_0, 0)))
- + {
- + set = single_set (insn);
- + if (set == NULL
- + || GET_CODE (SET_DEST (set)) == REG)
- + { /* Since reg may have been reused. */
- + remove_note (insn, note);
- + }
- + }
- + }
- +
- + } /* for (insn = basic_block_head[block]; */
- + } /* for (block = 0; block < n_basic_blocks; block++) */
- + } /* if (n_basic_blocks > 0) */
- + } /* replace_reload_registers (file, f) */
- +
- +
- +
- + /* Returns a hard register regno, if the contents of entry regno in
- + last_reloads array equals to MEM, FIRST_PSEUDO_REGISTER otherwise. */
- +
- + static int
- + find_last_reload (rtx mem)
- + {
- + register int regno;
- +
- + if (GET_CODE (mem) != MEM)
- + abort ();
- +
- + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- + /* tevid added test of LAST_RELOAD (regno) != NULL and XEXPs */
- + if (LAST_RELOAD (regno) != NULL
- + && rtx_equal_p (XEXP (LAST_RELOAD (regno), 0), XEXP (mem, 0)))
- + return (regno);
- +
- + return (FIRST_PSEUDO_REGISTER);
- + }
- +
- + /* Keep track of effect of pat on last_reloads[]. Note that making
- + an error will not effect the correctness of the code. */
- +
- + static void
- + update_last_reloads (rtx pat)
- + {
- + register int i, j, regno, nregs;
- + rtx set_src, set_dest;
- + register char *fmt;
- + register RTX_CODE code = GET_CODE (pat);
- +
- + switch (GET_CODE (pat))
- + {
- + case SET:
- + case CLOBBER:
- + set_dest = SET_DEST (pat);
- + if (GET_CODE (set_dest) == REG)
- + {
- + regno = REGNO (set_dest);
- + nregs = HARD_REGNO_NREGS (regno, GET_MODE (set_dest));
- +
- + if (nregs != 1)
- + {
- + bzero (last_reloads, sizeof last_reloads);
- + }
- + else
- + {
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + if (LAST_RELOAD (i))
- + {
- + if (reg_overlap_mentioned_p (set_dest, LAST_RELOAD (i)))
- + {
- + LAST_RELOAD (i) = NULL;
- + }
- + }
- + }
- + }
- + }
- + else if (GET_CODE (set_dest) == SUBREG)
- + {
- + if (GET_CODE (SUBREG_REG (set_dest)) == REG)
- + {
- + regno = REGNO (SUBREG_REG (set_dest)) + SUBREG_WORD (set_dest);
- + nregs
- + = HARD_REGNO_NREGS (regno, GET_MODE (SUBREG_REG (set_dest)));
- +
- + if (nregs != 1)
- + {
- + bzero (last_reloads, sizeof last_reloads);
- + }
- + else
- + {
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + if (LAST_RELOAD (i))
- + {
- + if (reg_overlap_mentioned_p (SUBREG_REG (set_dest),
- + LAST_RELOAD (i)))
- + {
- + LAST_RELOAD (i) = NULL;
- + }
- + }
- + }
- + }
- + }
- + return;
- + }
- + else if (GET_CODE (set_dest) == MEM)
- + {
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + if (LAST_RELOAD (i)
- + && true_dependence (set_dest, LAST_RELOAD (i)))
- + LAST_RELOAD (i) = 0;
- + update_last_reloads (XEXP (set_dest, 0));
- + return;
- + }
- + case CALL:
- + for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
- + if (call_used_regs[j])
- + LAST_RELOAD (j) = NULL;
- + return;
- + case PRE_DEC:
- + case PRE_INC:
- + case POST_DEC:
- + case POST_INC:
- + if (GET_CODE (XEXP (pat ,0)) == REG)
- + {
- + regno = REGNO (XEXP (pat ,0));
- + nregs = HARD_REGNO_NREGS (regno, GET_MODE (XEXP (pat ,0)));
- +
- + if (nregs != 1)
- + {
- + bzero (last_reloads, sizeof last_reloads);
- + }
- + else
- + {
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + if (LAST_RELOAD (i))
- + {
- + if (reg_overlap_mentioned_p (XEXP (pat ,0), LAST_RELOAD (i)))
- + {
- + LAST_RELOAD (i) = NULL;
- + }
- + }
- + }
- + }
- + }
- + return;
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + case REG:
- + /*case SUBREG:*/
- + /* do nothing */
- + return;
- + } /* switch (GET_CODE (pat)) */
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + {
- + if( XEXP (pat, i))
- + update_last_reloads (XEXP (pat, i));
- + }
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + update_last_reloads (XVECEXP (pat, i, j));
- + }
- + }
- +
- + /* tsl - end */
- +
- + static unsigned int largest_himode_const;
- +
- + #define MAX_COMP_REGS 4
- +
- + struct sign_extension_info {
- + rtx insn_set;
- + int num_comp_regs;
- + struct comp_to_reg {
- + int regno;
- + rtx comp_insn;
- + rtx *where;
- + unsigned char for_equality;
- + } compare_to_reg [MAX_COMP_REGS];
- + };
- + static struct sign_extension_info * sign_extension_infos;
- +
- + static void
- + sign_extension_reduction (loop_start, loop_end)
- + rtx loop_start, loop_end;
- + {
- + int cur_max_regnum = max_reg_num ();
- + int found_sign_extension = 0, regno, i, j;
- + rtx insn, sign_ext_reg;
- +
- + sign_extension_infos
- + = (struct sign_extension_info *)
- + alloca ( sizeof (struct sign_extension_info) * cur_max_regnum);
- + bzero (sign_extension_infos,
- + sizeof (struct sign_extension_info) * cur_max_regnum);
- + largest_himode_const = 256;
- + if (sizeof (unsigned int) <= GET_MODE_SIZE (HImode))
- + {
- + return ;
- + }
- + for (i = 0; i < GET_MODE_SIZE (HImode); i++)
- + {
- + largest_himode_const *= 256;
- + }
- + largest_himode_const -= 1;
- + /* Go over loop - mark registers set by sign extension */
- + for (insn = loop_start; insn && insn != loop_end; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTEND
- + && GET_MODE (SET_DEST (PATTERN (insn))) == SImode
- + && GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == HImode)
- + { /* Found one. */
- + regno = REGNO (SET_DEST (PATTERN (insn)));
- + if ( regno >= cur_max_regnum)
- + {
- + return;
- + }
- + found_sign_extension++;
- + if (sign_extension_infos[regno].insn_set)
- + {
- + return;
- + }
- + sign_extension_infos[regno].insn_set = insn;
- + }
- + }
- + if (!found_sign_extension || insn != loop_end)
- + {
- + return;
- + }
- + /* Find all uses of each register marked above */
- + for (i = FIRST_PSEUDO_REGISTER; i < cur_max_regnum; i++)
- + {
- + if (sign_extension_infos[i].insn_set)
- + {
- + for (insn = loop_start; insn != loop_end; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
- + || GET_CODE (insn) == JUMP_INSN)
- + {
- +
- + validate_all_references (i, insn, PATTERN (insn));
- + }
- + }
- + }
- + }
- + for (i = FIRST_PSEUDO_REGISTER; i < cur_max_regnum; i++)
- + {
- + if (sign_extension_infos[i].insn_set)
- + {
- + sign_ext_reg = SET_DEST (PATTERN (sign_extension_infos[i].insn_set));
- + if (reg_used_between_p (sign_ext_reg,
- + get_insns (), loop_start) ||
- + reg_used_between_p (sign_ext_reg,
- + loop_end, NULL)
- + )
- + {
- + sign_extension_infos[i].insn_set = NULL;
- + }
- + }
- + }
- + /* Check which registers can be sign extension reduced */
- + for (i = FIRST_PSEUDO_REGISTER; i < cur_max_regnum; i++)
- + {
- + if (sign_extension_infos[i].insn_set)
- + {
- + j = 0;
- + while (j < sign_extension_infos[i].num_comp_regs
- + && sign_extension_infos[i].insn_set)
- + {
- + regno = sign_extension_infos[i].compare_to_reg[j].regno;
- + if (regno < FIRST_PSEUDO_REGISTER)
- + {
- + sign_extension_infos[i].insn_set = NULL;
- + }
- + if (sign_extension_infos[regno].insn_set == NULL)
- + {
- + sign_extension_infos[i].insn_set = NULL;
- + }
- + j++;
- + }
- + }
- + }
- + /* Do the optimization. */
- + for (i = FIRST_PSEUDO_REGISTER; i < cur_max_regnum; i++)
- + {
- + if (sign_extension_infos[i].insn_set)
- + {
- + rtx subreg, strict_subreg;
- +
- + subreg
- + = gen_rtx (SUBREG, HImode,
- + SET_DEST (PATTERN (sign_extension_infos[i].insn_set)),
- + 0);
- + strict_subreg = gen_rtx (STRICT_LOW_PART, 0, subreg);
- + emit_insn_before (gen_rtx (SET, 0,
- + SET_DEST (PATTERN (sign_extension_infos[i].insn_set)),
- + const0_rtx), loop_start);
- + emit_insn_before (gen_rtx (USE, 0,
- + SET_DEST (PATTERN (sign_extension_infos[i].insn_set))),
- + loop_start);
- + SET_DEST (PATTERN (sign_extension_infos[i].insn_set))
- + = strict_subreg;
- + SET_SRC (PATTERN (sign_extension_infos[i].insn_set))
- + = XEXP (SET_SRC (PATTERN (sign_extension_infos[i].insn_set)), 0);
- + INSN_CODE (sign_extension_infos[i].insn_set) = -1;
- + j = 0;
- + while (j < sign_extension_infos[i].num_comp_regs)
- + {
- + if (sign_extension_infos[i].compare_to_reg[j].for_equality == 0)
- + {
- + *sign_extension_infos[i].compare_to_reg[j].where
- + = subreg;
- + INSN_CODE (sign_extension_infos[i].compare_to_reg[j].comp_insn)
- + = -1;
- + }
- + j++;
- + }
- + }
- + }
- + }
- +
- +
- + static void
- + validate_all_references (regno, insn, pat)
- + int regno;
- + rtx insn, pat;
- + {
- + register RTX_CODE code = GET_CODE (pat);
- + register int i, j, val;
- + register char *fmt;
- + int num_comp_regs, comp_regno, for_equality = 0;
- + rtx next;
- +
- + switch (code)
- + {
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + return ;
- +
- + case REG:
- + if (REGNO (pat) == regno)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + break;
- +
- + case SET:
- + if (GET_CODE (SET_DEST (pat)) == REG
- + && REGNO (SET_DEST (pat)) == regno
- + && sign_extension_infos[REGNO (SET_DEST (pat))].insn_set != insn)
- + {
- + if (GET_CODE (SET_SRC (pat)) != CONST_INT)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + if (GET_MODE (SET_DEST (pat)) != SImode)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + val = XINT (SET_SRC (pat), 0);
- + if (val < 0 || val > largest_himode_const)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + validate_all_references (regno, insn, SET_SRC (pat));
- + return;
- + }
- + else if (GET_CODE (SET_DEST (pat)) == REG
- + && REGNO (SET_DEST (pat)) == regno
- + && sign_extension_infos[REGNO (SET_DEST (pat))].insn_set == insn)
- + {
- + return;
- + }
- + break;
- +
- + case AND:
- + if (GET_CODE (XEXP (pat, 0)) == REG
- + && REGNO (XEXP (pat, 0)) == regno)
- + {
- + if (GET_CODE (XEXP (pat, 1)) != CONST_INT)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + if (GET_MODE (XEXP (pat, 0)) != SImode)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + val = XINT (XEXP (pat, 1), 0);
- + if (val < 0 || val > largest_himode_const)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + validate_all_references (regno, insn, XEXP (pat, 1));
- + return;
- + }
- + else if (GET_CODE (XEXP (pat, 1)) == REG
- + && REGNO (XEXP (pat, 1)) == regno)
- + {
- + if (GET_CODE (XEXP (pat, 0)) != CONST_INT)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + if (GET_MODE (XEXP (pat, 1)) != SImode)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + val = XINT (XEXP (pat, 0), 0);
- + if (val < 0 || val > largest_himode_const)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + validate_all_references (regno, insn, XEXP (pat, 0));
- + return;
- + }
- + break;
- +
- + case COMPARE:
- + next = NEXT_INSN (insn);
- + if (GET_CODE (next) == JUMP_INSN
- + && GET_CODE (PATTERN (next)) == SET
- + && SET_DEST (PATTERN (next)) == pc_rtx
- + && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE
- + && (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == NE
- + ||
- + GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == EQ))
- + {
- + for_equality = 1;
- + }
- + if (GET_CODE (XEXP (pat, 0)) == REG
- + && REGNO (XEXP (pat, 0)) == regno)
- + {
- + if (GET_MODE (XEXP (pat, 0)) != SImode)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + if (GET_CODE (XEXP (pat, 1)) == CONST_INT)
- + {
- + val = XINT (XEXP (pat, 1), 0);
- + if (for_equality == 0 || val < 0 || val > largest_himode_const)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + }
- + else if (GET_CODE (XEXP (pat, 1)) == REG)
- + {
- + if (GET_MODE (XEXP (pat, 1)) != SImode)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + #ifndef HAVE_cmphi
- + sign_extension_infos[regno].insn_set = NULL;
- + #else
- + if (!HAVE_cmphi)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + #endif
- + comp_regno = REGNO (XEXP (pat, 1));
- + if (!sign_extension_infos[comp_regno].insn_set)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + else
- + {
- + num_comp_regs
- + = sign_extension_infos[regno].num_comp_regs;
- + if (num_comp_regs >= MAX_COMP_REGS)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + sign_extension_infos[regno].
- + compare_to_reg[num_comp_regs].where =
- + &XEXP (pat, 0);
- + sign_extension_infos[regno].
- + compare_to_reg[num_comp_regs].comp_insn = insn;
- + sign_extension_infos[regno].
- + compare_to_reg[num_comp_regs].regno =
- + comp_regno;
- + sign_extension_infos[regno].
- + compare_to_reg[num_comp_regs].for_equality = for_equality;
- + sign_extension_infos[regno].num_comp_regs++;
- + }
- + }
- + else
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + validate_all_references (regno, insn, XEXP (pat, 1));
- + }
- + return;
- + }
- + else if (GET_CODE (XEXP (pat, 1)) == REG
- + && REGNO (XEXP (pat, 1)) == regno)
- + {
- + if (GET_MODE (XEXP (pat, 1)) != SImode)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + if (GET_CODE (XEXP (pat, 0)) == CONST_INT)
- + {
- + val = XINT (XEXP (pat, 0), 0);
- + if (for_equality == 0 || val < 0 || val > largest_himode_const)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + }
- + else if (GET_CODE (XEXP (pat, 0)) == REG)
- + {
- + if (GET_MODE (XEXP (pat, 0)) != SImode)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + #ifndef HAVE_cmphi
- + sign_extension_infos[regno].insn_set = NULL;
- + #else
- + if (!HAVE_cmphi)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + #endif
- + comp_regno = REGNO (XEXP (pat, 0));
- + if (!sign_extension_infos[comp_regno].insn_set)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + else
- + {
- + num_comp_regs
- + = sign_extension_infos[regno].num_comp_regs;
- + if (num_comp_regs >= MAX_COMP_REGS)
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + }
- + sign_extension_infos[regno].
- + compare_to_reg[num_comp_regs].where =
- + &XEXP (pat, 1);
- + sign_extension_infos[regno].
- + compare_to_reg[num_comp_regs].comp_insn = insn;
- + sign_extension_infos[regno].
- + compare_to_reg[num_comp_regs].regno =
- + comp_regno;
- + sign_extension_infos[regno].
- + compare_to_reg[num_comp_regs].for_equality = for_equality;
- + sign_extension_infos[regno].num_comp_regs++;
- + }
- + }
- + else
- + {
- + sign_extension_infos[regno].insn_set = NULL;
- + validate_all_references (regno, insn, XEXP (pat, 0));
- + }
- + return;
- + }
- + break;
- +
- +
- + }
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + {
- + if( XEXP (pat, i))
- + validate_all_references (regno, insn, XEXP (pat, i));
- + }
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + validate_all_references (regno, insn, XVECEXP (pat, i, j));
- + }
- + }
- +
- + #define MAX_WHERE 5
- + #define MAX_DISAMBIGS 3
- + #define MAX_MEM_REFS 10
- + #define NO_REG -1
- + #define UNKNOWN -2
- +
- + static struct mem_ref {
- + /* Pointers to where this mem_ref is used. */
- + rtx * where[MAX_WHERE];
- + /* Number of references to this mem_ref in the loop. */
- + int num_ref;
- + /* The base register number if any, else -1. */
- + int base_regno;
- + /* The base register number if. */
- + rtx base_reg;
- + /* The index register number if any, else -1. */
- + int index_regno;
- + /* The index register number if. */
- + rtx index_reg;
- + /* Bit-map if bit# i is set then this element is true_dependence on
- + element# i. Assumes MAX_MEM_REFS < (sizeof (int) * 8) */
- + int conflict;
- + /* If 1 then this element is a varying address over the loop - or
- + should not be lifted into register for some other reason. */
- + unsigned int varying:1;
- + /* If 1 then this mem_ref is stored into in the loop. */
- + unsigned int stored:1;
- + /* If 1 then the first reference to the mem_ref in the loop is a store. */
- + unsigned int first_stored:1;
- + } *mem_refs;
- +
- + static struct disambig{
- + rtx reg;
- + int inc_val;
- + } runtime_disambigs [MAX_DISAMBIGS];
- +
- + static int num_mem_refs = 0;
- + static int max_regs_before_lift;
- +
- + extern rtx gen_jump ();
- + /*
- + Shadow memory locations that are stored into in the loop and can
- + be memory disambiguated over the loop. These are loaded into a register
- + before the loop, accessed from and into the register during the loop
- + and stored from the register at the loop end.
- + */
- + static void
- + lift_stores (loop_start, loop_end)
- + rtx loop_start, loop_end;
- + {
- + rtx insn, lift_reg, set, new_label, new_label_insn, new_jump_insn, new_jump,
- + new_loop_label, new_loop_jump, new_compare, new_compare_insn, copy_insn;
- + int i, j, num_candidates, jmask, imask, num_lifted, num_possible,
- + indx_possible, num_runtime_disambigs, disambig_mask, found, dummy;
- + char * may_not_optimize;
- +
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream, "lift stores from %d to %d\n",
- + INSN_UID (loop_start), INSN_UID (loop_end));
- + }
- + /* Handle only loops with no inner jumps labels or calls */
- + if (GET_CODE (PREV_INSN (loop_end)) != JUMP_INSN)
- + {
- + return;
- + }
- + if (GET_CODE (SET_SRC (PATTERN (PREV_INSN (loop_end)))) != IF_THEN_ELSE)
- + {
- + return;
- + }
- + if (GET_CODE (NEXT_INSN (loop_start)) != CODE_LABEL)
- + {
- + return;
- + }
- + for (insn = NEXT_INSN (NEXT_INSN (loop_start));
- + insn != PREV_INSN (loop_end); insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN
- + || GET_CODE (insn) == CODE_LABEL)
- + {
- + return;
- + }
- + }
- + /* Compute n_times_set */
- + max_regs_before_lift = max_reg_num () + 1;
- + n_times_set = (short *) alloca (max_regs_before_lift * sizeof (short));
- + bzero (n_times_set, max_regs_before_lift * sizeof (short));
- + may_not_optimize = (char *) alloca (max_regs_before_lift); /* not used */
- + count_loop_regs_set (loop_start, loop_end, may_not_optimize, NULL,
- + &dummy, max_regs_before_lift);
- +
- + mem_refs = (struct mem_ref *) alloca (sizeof (struct mem_ref) * MAX_MEM_REFS);
- + bzero (mem_refs, sizeof (struct mem_ref) * MAX_MEM_REFS);
- + /* Locate all memory refs into the mem_refs array. */
- + num_mem_refs = 0;
- + for (insn = loop_start; insn != loop_end; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + mark_mem_refs (PATTERN (insn), &PATTERN (insn));
- + if (num_mem_refs >= MAX_MEM_REFS)
- + {
- + return;
- + }
- + }
- + }
- + if (num_mem_refs == 0)
- + {
- + return;
- + }
- + /* Check each non varying mem_ref against all others to see if it can
- + be memory disambiguated */
- + num_candidates = 0;
- + for (i = 0; i < num_mem_refs; i++)
- + {
- + if (mem_refs[i].varying == 0 && mem_refs[i].stored == 1)
- + {
- + num_candidates++;
- + imask = 1 << i;
- + for (j = 0; j < num_mem_refs; j++)
- + {
- + jmask = (1 << j);
- + if (j != i && !(mem_refs[i].conflict & jmask))
- + {
- + if (true_dependence (*(mem_refs[i].where[0]),
- + *(mem_refs[j].where[0])))
- + {
- + mem_refs[i].conflict |= jmask;
- + mem_refs[j].conflict |= imask;
- + }
- + }
- + }
- + }
- + }
- + /* Lift all the mem_refs that can be lifted. */
- + num_lifted = 0;
- + num_possible = 0;
- + for (i = 0; i < num_mem_refs; i++)
- + {
- + if (mem_refs[i].varying == 0 && mem_refs[i].stored == 1)
- + {
- + num_possible++;
- + indx_possible = i;
- + }
- + if (mem_refs[i].varying == 0 && mem_refs[i].stored == 1
- + && mem_refs[i].conflict == 0)
- + {
- + num_lifted++;
- + lift_reg = gen_reg_rtx (GET_MODE (*(mem_refs[i].where[0])));
- + if (mem_refs[i].first_stored)
- + {
- + emit_insn_before ( gen_rtx (SET, 0, lift_reg,
- + CONST0_RTX ( GET_MODE (lift_reg))),
- + loop_start);
- + }
- + else
- + {
- + emit_insn_before ( gen_rtx (SET, 0, lift_reg,
- + copy_rtx (*(mem_refs[i].where[0]))),
- + loop_start);
- + }
- + emit_insn_after ( gen_rtx (SET, 0, copy_rtx (*(mem_refs[i].where[0])),
- + lift_reg),
- + loop_end);
- + /*emit_insn_after (gen_rtx (USE, 0, lift_reg),
- + NEXT_INSN (loop_end));*/
- + for (j = 0; j < mem_refs[i].num_ref; j++)
- + {
- + *(mem_refs[i].where[j]) = lift_reg;
- + }
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream,
- + "The following memory operand lifted into reg %d during loop:\n",
- + REGNO (lift_reg));
- + tdebug_rtx (SET_DEST (PATTERN (NEXT_INSN (loop_end))),
- + loop_dump_stream);
- + fprintf (loop_dump_stream, "\n");
- + }
- + }
- + }
- + if (num_lifted == 0 && num_possible == 1 && flag_runtime_lift_stores)
- + { /* Do runtime disambiguation if possible */
- + if (mem_refs[indx_possible].index_regno != NO_REG
- + || mem_refs[indx_possible].base_regno == NO_REG
- + || mem_refs[indx_possible].base_regno == UNKNOWN)
- + {
- + return;
- + }
- + if (GET_MODE (mem_refs[indx_possible].base_reg) != SImode)
- + {
- + return;
- + }
- + num_runtime_disambigs = 0;
- + for (i = 0; i < num_mem_refs; i++)
- + {
- + disambig_mask = 1 << i;
- + if (mem_refs[indx_possible].conflict & disambig_mask)
- + {
- + if (num_runtime_disambigs >= MAX_DISAMBIGS)
- + {
- + return;
- + }
- + if (mem_refs[i].base_regno == NO_REG
- + || mem_refs[i].base_regno == UNKNOWN
- + || (mem_refs[i].index_regno != UNKNOWN
- + && mem_refs[i].index_regno != NO_REG))
- + {
- + return;
- + }
- + if (n_times_set[mem_refs[i].base_regno] > 1)
- + {
- + return;
- + }
- + if (GET_MODE (mem_refs[i].base_reg)
- + != GET_MODE (mem_refs[indx_possible].base_reg))
- + {
- + return;
- + }
- + runtime_disambigs[num_runtime_disambigs].reg
- + = mem_refs[i].base_reg;
- + runtime_disambigs[num_runtime_disambigs].inc_val = 0;
- + num_runtime_disambigs++;
- + }
- + }
- + /* Now find the setting of each of the registers of the disambigs */
- + for (i = 0; i < num_runtime_disambigs; i++)
- + {
- + if (n_times_set[REGNO (runtime_disambigs[i].reg)])
- + {
- + insn = loop_start;
- + found = 0;
- + while (insn != loop_end && !found)
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + set = single_set (insn);
- + if (set && GET_CODE (SET_DEST (set)) == REG
- + && REGNO (SET_DEST (set))
- + == REGNO (runtime_disambigs[i].reg) )
- + {
- + found = 1;
- + if (!rtx_equal_p (SET_DEST (set),
- + runtime_disambigs[i].reg))
- + {
- + return;
- + }
- + if ((GET_CODE (SET_SRC (set)) == PLUS
- + || GET_CODE (SET_SRC (set)) == MINUS)
- + && rtx_equal_p (SET_DEST (set),
- + XEXP (SET_SRC (set), 0))
- + && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
- + {
- + runtime_disambigs[i].inc_val
- + = XINT (XEXP (SET_SRC (set), 1), 0)
- + * (GET_CODE (SET_SRC (set)) == PLUS
- + ? 1 : -1);
- + }
- + else
- + {
- + return;
- + }
- + }
- + }
- + if (!found)
- + {
- + insn = NEXT_INSN (insn);
- + }
- + }
- + if (!found)
- + {
- + return;
- + }
- + }
- + }
- + /* The runtime disambiguation is possible - now do it. */
- + /* Make a copy of the loop. */
- + new_label = gen_label_rtx ();
- + new_label_insn
- + = emit_label_after (new_label, PREV_INSN (loop_start));
- + new_loop_label = new_label_insn;
- + ++LABEL_NUSES (new_label_insn);
- + new_jump = copy_rtx (PATTERN (PREV_INSN (loop_end)));
- + if (XEXP (SET_SRC (new_jump), 1) == pc_rtx)
- + {
- + XEXP (SET_SRC (new_jump), 2)
- + = gen_rtx (LABEL_REF, VOIDmode, new_label);
- + }
- + else
- + {
- + XEXP (SET_SRC (new_jump), 1)
- + = gen_rtx (LABEL_REF, VOIDmode, new_label);
- + }
- + new_jump_insn = emit_jump_insn_after (new_jump, new_label_insn);
- + INSN_CODE (new_jump_insn) = recog (new_jump, new_jump_insn);
- + new_loop_jump = new_jump_insn;
- + JUMP_LABEL (new_jump_insn) = new_label_insn;
- + /* The body of the original loop is moved to the new loop */
- + NEXT_INSN (new_label_insn) = NEXT_INSN (NEXT_INSN (loop_start));
- + PREV_INSN (NEXT_INSN (new_label_insn)) = new_label_insn;
- + PREV_INSN (new_jump_insn) = PREV_INSN (PREV_INSN (loop_end));
- + NEXT_INSN ( PREV_INSN (new_jump_insn)) = new_jump_insn;
- + NEXT_INSN (NEXT_INSN (loop_start)) = PREV_INSN (loop_end);
- + PREV_INSN (PREV_INSN (loop_end)) = NEXT_INSN (loop_start);
- + /* Now make a copy of the loop in between the original label and jump. */
- + insn = NEXT_INSN (new_label_insn);
- + copy_insn = NEXT_INSN (loop_start);
- + while (insn != new_jump_insn)
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + copy_insn = emit_insn_after (copy_rtx (PATTERN (insn)), copy_insn);
- + }
- + insn = NEXT_INSN (insn);
- + }
- + /* Now make a jump around the second copy of the loop. */
- + new_label = gen_label_rtx ();
- + new_label_insn
- + = emit_label_after (new_label, loop_end);
- + new_jump_insn = emit_jump_insn_after (gen_jump (new_label_insn),
- + PREV_INSN (loop_start));
- + JUMP_LABEL (new_jump_insn) = new_label_insn;
- + ++LABEL_NUSES (new_label_insn);
- + emit_barrier_after (new_jump_insn);
- + /* Now make a label just before loop start */
- + new_label = gen_label_rtx ();
- + new_label_insn
- + = emit_label_after (new_label, PREV_INSN (loop_start));
- + ++LABEL_NUSES (new_label_insn);
- + /* Now compare the base_reg of the mem_ref to be lifted with
- + each of the base_regs that it conflicts with. Jump around the
- + disambiguated loop if they conflict at runtime. */
- + for (i = 0; i < num_runtime_disambigs; i++)
- + {
- + if (runtime_disambigs[i].inc_val != 0)
- + {
- + new_compare
- + = gen_cmpsi_1 (runtime_disambigs[i].reg,
- + mem_refs[indx_possible].base_reg);
- + new_compare_insn
- + = emit_insn_before (new_compare, new_loop_label);
- + new_jump = copy_rtx (new_jump);
- + if (runtime_disambigs[i].inc_val > 0)
- + {
- + GET_CODE (XEXP (SET_SRC (new_jump), 0)) = LE;
- + }
- + else
- + {
- + GET_CODE (XEXP (SET_SRC (new_jump), 0)) = GE;
- + }
- + XEXP (SET_SRC (new_jump), 1)
- + = gen_rtx (LABEL_REF, VOIDmode, new_label);
- + XEXP (SET_SRC (new_jump), 2) = pc_rtx;
- + ++LABEL_NUSES (new_label_insn);
- + new_jump_insn
- + = emit_jump_insn_after (new_jump, new_compare_insn);
- + JUMP_LABEL (new_jump_insn) = new_label_insn;
- + INSN_CODE (new_jump_insn)
- + = recog (new_jump, new_jump_insn);
- + }
- + }
- + /* Now do the lifting */
- + lift_reg = gen_reg_rtx (GET_MODE (*(mem_refs[indx_possible].where[0])));
- + if (mem_refs[indx_possible].first_stored)
- + {
- + emit_insn_before ( gen_rtx (SET, 0, lift_reg,
- + CONST0_RTX ( GET_MODE (lift_reg))),
- + new_loop_label);
- + }
- + else
- + {
- + emit_insn_before ( gen_rtx (SET, 0, lift_reg,
- + copy_rtx (*(mem_refs[indx_possible].where[0]))),
- + new_loop_label);
- + }
- + emit_insn_after ( gen_rtx (SET, 0,
- + copy_rtx (*(mem_refs[indx_possible].where[0])),
- + lift_reg),
- + new_loop_jump);
- + /*emit_insn_after (gen_rtx (USE, 0, lift_reg),
- + NEXT_INSN (new_loop_jump));*/
- + emit_insn_after (gen_rtx (CLOBBER, 0, lift_reg), loop_end);
- + for (j = 0; j < mem_refs[indx_possible].num_ref; j++)
- + {
- + *(mem_refs[indx_possible].where[j]) = lift_reg;
- + }
- + emit_note_before (NOTE_INSN_LOOP_BEG, new_loop_label);
- + emit_note_before (NOTE_INSN_LOOP_END, NEXT_INSN (new_loop_jump));
- + if (loop_dump_stream)
- + {
- + fprintf (loop_dump_stream,
- + "The following memory operand RUNTIME lifted into reg %d during loop:\n",
- + REGNO (lift_reg));
- + tdebug_rtx (SET_DEST (PATTERN (NEXT_INSN (NEXT_INSN (new_loop_jump)))),
- + loop_dump_stream);
- + fprintf (loop_dump_stream, "\n");
- + }
- + }
- + }
- +
- +
- + /*
- + Go over PAT locate all mem_refs and insert them into the mem_refs
- + structure. WHERE is the location of PAT. */
- + static void
- + mark_mem_refs (pat, where)
- + rtx pat;
- + rtx *where;
- + {
- + register RTX_CODE code = GET_CODE (pat);
- + register int i, j;
- + register char *fmt;
- +
- + switch (code)
- + {
- + case HIGH:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case LABEL_REF:
- + case PC:
- + case CC0:
- + return ;
- +
- + case SET:
- + mark_mem_refs (SET_SRC (pat), &SET_SRC (pat));
- + if (GET_CODE (SET_DEST (pat)) == MEM)
- + {
- + insert_mem_ref (SET_DEST (pat), &SET_DEST (pat), 1);
- + }
- + return;
- +
- + case MEM:
- + insert_mem_ref (pat, where, 0);
- + return;
- +
- + }
- +
- + fmt = GET_RTX_FORMAT (code);
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + if (fmt[i] == 'e')
- + {
- + if( XEXP (pat, i))
- + mark_mem_refs (XEXP (pat, i), &XEXP (pat, i));
- + }
- + else if (fmt[i] == 'E' || fmt[i] == 'V')
- + {
- + for (j = 0; j < XVECLEN (pat, i); j++)
- + mark_mem_refs (XVECEXP (pat, i, j), &XVECEXP (pat, i, j));
- + }
- + }
- +
- +
- + /*
- + Insert the memory reference MEM into the mem_refs structure.
- + WHERE is location of MEM.
- + if IS_STORE is 1 then MEM is being stored into. */
- +
- + static void
- + insert_mem_ref (mem, where, is_store)
- + rtx mem, *where;
- + int is_store;
- + {
- + int i, j, indx, found, base_regno, index_regno;
- + rtx mem_addr, base_reg, index_reg;
- +
- + if (num_mem_refs >= MAX_MEM_REFS)
- + {
- + return;
- + }
- + /* Find where in table to put mem. */
- + i = 0;
- + found = 0;
- + while (i < num_mem_refs && !found)
- + {
- + if (rtx_equal_p (mem, *(mem_refs[i].where[0])))
- + {
- + found = 1;
- + }
- + else
- + {
- + i++;
- + }
- + }
- + if (!found)
- + {
- + num_mem_refs++;
- + }
- + if (i >= MAX_MEM_REFS)
- + {
- + return;
- + }
- +
- + indx = i;
- + j = mem_refs[indx].num_ref;
- + if (j >= MAX_WHERE)
- + {
- + mem_refs[indx].varying = 1;
- + return;
- + }
- + mem_refs[indx].where[j] = where;
- + mem_refs[indx].num_ref++;
- + if (is_store)
- + {
- + mem_refs[indx].stored = 1;
- + if (j == 0)
- + {
- + mem_refs[indx].first_stored = 1;
- + }
- + }
- + if (found == 1)
- + {
- + return;
- + }
- + mem_refs[indx].varying = rtx_addr_varies_p (mem);
- + /* Now analyze the mem to find it's base and index registers if any */
- + mem_refs[indx].base_regno = NO_REG;
- + mem_refs[indx].index_regno = NO_REG;
- + index_reg = NULL;
- + base_regno = NO_REG;
- + index_regno = NO_REG;
- + base_reg = NULL;
- + mem_addr = XEXP (mem, 0);
- + if (GET_CODE (mem_addr) == SYMBOL_REF)
- + {
- + return;
- + }
- + if (GET_CODE (mem_addr) == REG)
- + {
- + base_regno = REGNO (mem_addr);
- + base_reg = (mem_addr);
- + }
- + if (GET_CODE (mem_addr) == PLUS)
- + {
- + if (GET_CODE (XEXP (mem_addr, 0)) == REG)
- + {
- + base_regno = REGNO (XEXP (mem_addr, 0));
- + base_reg = (XEXP (mem_addr, 0));
- + if (GET_CODE (XEXP (mem_addr, 1)) == REG)
- + {
- + index_regno = REGNO (XEXP (mem_addr, 1));
- + index_reg = (XEXP (mem_addr, 1));
- + }
- + else if (GET_CODE (XEXP (mem_addr, 1)) != CONST_INT
- + && GET_CODE (XEXP (mem_addr, 1)) != CONST
- + && GET_CODE (XEXP (mem_addr, 1)) != SYMBOL_REF)
- + {
- + index_regno = UNKNOWN;
- + }
- + }
- + else if (GET_CODE (XEXP (mem_addr, 0)) == MULT)
- + {
- + if (GET_CODE (XEXP (mem_addr, 1)) == REG)
- + {
- + base_regno = REGNO (XEXP (mem_addr, 1));
- + base_reg = (XEXP (mem_addr, 1));
- + }
- + else if (GET_CODE (XEXP (mem_addr, 1)) != CONST_INT
- + && GET_CODE (XEXP (mem_addr, 1)) != CONST
- + && GET_CODE (XEXP (mem_addr, 1)) != SYMBOL_REF)
- + {
- + base_regno = UNKNOWN;
- + }
- + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == REG
- + && GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == CONST_INT)
- + {
- + index_regno = REGNO (XEXP (XEXP (mem_addr, 0), 0));
- + index_reg = (XEXP (XEXP (mem_addr, 0), 0));
- + }
- + else
- + {
- + index_regno = UNKNOWN;
- + }
- + }
- + else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS)
- + {
- + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == REG)
- + {
- + base_regno = REGNO (XEXP (XEXP (mem_addr, 0), 0));
- + base_reg = (XEXP (XEXP (mem_addr, 0), 0));
- + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG)
- + {
- + index_regno = REGNO (XEXP (XEXP (mem_addr, 0), 1));
- + index_reg = (XEXP (XEXP (mem_addr, 0), 1));
- + }
- + else if (GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) != CONST_INT
- + && GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) != CONST
- + && GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) != SYMBOL_REF)
- + {
- + index_regno = UNKNOWN;
- + }
- + }
- + else if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == MULT)
- + {
- + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG)
- + {
- + base_regno = REGNO (XEXP (XEXP (mem_addr, 0), 1));
- + base_reg = (XEXP (XEXP (mem_addr, 0), 1));
- + }
- + if (GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == REG
- + && GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) == CONST_INT)
- + {
- + index_regno = REGNO (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0));
- + index_reg = (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0));
- + }
- + else
- + {
- + index_regno = UNKNOWN;
- + }
- + }
- + if (GET_CODE (XEXP (mem_addr, 1)) != SYMBOL_REF
- + && GET_CODE (XEXP (mem_addr, 1)) != CONST
- + && GET_CODE (XEXP (mem_addr, 1)) != CONST_INT)
- + {
- + index_regno = UNKNOWN;
- + base_regno = UNKNOWN;
- + }
- + }
- + }
- + else if (GET_CODE (mem_addr) == MULT)
- + {
- + if (GET_CODE (XEXP (mem_addr, 0)) == REG
- + && GET_CODE (XEXP (mem_addr, 1)) == CONST_INT)
- + {
- + index_regno = REGNO (XEXP (mem_addr, 0));
- + index_reg = (XEXP (mem_addr, 0));
- + }
- + else
- + {
- + index_regno = UNKNOWN;
- + }
- + }
- + mem_refs[indx].base_reg = base_reg;
- + mem_refs[indx].base_regno = base_regno;
- + mem_refs[indx].index_reg = index_reg;
- + mem_refs[indx].index_regno = index_regno;
- + if (base_regno == UNKNOWN || index_regno == UNKNOWN)
- + {
- + mem_refs[indx].varying = 1;
- + return;
- + }
- + if (base_regno >= max_regs_before_lift || index_regno >= max_regs_before_lift)
- + {
- + mem_refs[indx].varying = 1;
- + return;
- + }
- + if ( (base_regno == NO_REG || n_times_set[base_regno] == 0)
- + && (index_regno == NO_REG || n_times_set[index_regno] == 0))
- + {
- + mem_refs[indx].varying = 0;
- + }
- + if (MEM_VOLATILE_P (mem))
- + {
- + mem_refs[indx].varying = 1;
- + }
- + }
- +
- +
- + static void opt_reg_use_copy (f)
- + rtx f;
- + {
- + rtx insn, src, prev;
- + int i, length;
- + char * fmt;
- + for (insn = f; insn; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + if (GET_CODE (PATTERN (insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (insn))) == REG
- + && (prev = PREV_INSN (insn))
- + && GET_CODE (prev) == INSN
- + && GET_CODE (PATTERN (prev)) == SET
- + && rtx_equal_p (SET_SRC (PATTERN (insn)),
- + SET_DEST (PATTERN (prev))))
- + {
- + src = SET_SRC (PATTERN (prev));
- + fmt = GET_RTX_FORMAT (GET_CODE (src));
- + length = GET_RTX_LENGTH (GET_CODE (src));
- + for (i=0; i<length; i++)
- + {
- + if (fmt[i] == 'e'
- + && GET_CODE (XEXP (src, i)) == REG
- + && rtx_equal_p (XEXP (src, i), SET_DEST (PATTERN (insn))))
- + {
- + SET_DEST (PATTERN (insn)) = SET_SRC (PATTERN (insn));
- + SET_SRC (PATTERN (insn)) = XEXP (src, i);
- + SET_DEST (PATTERN (prev)) = XEXP (src, i);
- + emit_insn_after (gen_rtx (USE, 0,
- + SET_DEST (PATTERN (prev))),
- + prev);
- + break;
- + }
- + }
- + }
- + }
- + }
- }
- diff -rNci gcc-2.7.2/loop.h gcc-2.7.2p/loop.h
- *** gcc-2.7.2/loop.h Fri Jul 14 12:23:28 1995
- --- gcc-2.7.2p/loop.h Tue Jan 23 09:25:29 1996
- ***************
- *** 88,93 ****
- --- 88,97 ----
- unsigned maybe_dead : 1; /* 1 if this giv might be dead. In that case,
- we won't use it to eliminate a biv, it
- would probably lose. */
- + #ifdef REDUCE_INDEX
- + unsigned is_index_induc:1; /* 1 if this is actually the index portion
- + of a DEST_ADDR g_type intel1 */
- + #endif
- int lifetime; /* Length of life of this giv */
- int times_used; /* # times this giv is used. */
- rtx derive_adjustment; /* If nonzero, is an adjustment to be
- ***************
- *** 133,138 ****
- --- 137,144 ----
- unsigned nonneg : 1; /* 1 if we added a REG_NONNEG note for this. */
- unsigned reversed : 1; /* 1 if we reversed the loop that this
- biv controls. */
- + unsigned retry_celim :2; /*intel1 is >0 if we should retry compare
- + elimination at the end of strength reduction */
- };
-
- /* Definitions used by the basic induction variable discovery code. */
- ***************
- *** 146,152 ****
- extern int *uid_loop_num;
- extern int *loop_outer_loop;
- extern rtx *loop_number_exit_labels;
- - extern int *loop_number_exit_count;
- extern unsigned HOST_WIDE_INT loop_n_iterations;
- extern int max_reg_before_loop;
-
- --- 152,157 ----
- diff -rNci gcc-2.7.2/obstack.c gcc-2.7.2p/obstack.c
- *** gcc-2.7.2/obstack.c Sun Nov 26 19:57:12 1995
- --- gcc-2.7.2p/obstack.c Thu Jun 15 22:12:08 1995
- ***************
- *** 17,46 ****
-
- #include "obstack.h"
-
- ! /* NOTE BEFORE MODIFYING THIS FILE: This version number must be
- ! incremented whenever callers compiled using an old obstack.h can no
- ! longer properly call the functions in this obstack.c. */
- ! #define OBSTACK_INTERFACE_VERSION 1
-
- /* Comment out all this code if we are using the GNU C Library, and are not
- ! actually compiling the library itself, and the installed library
- ! supports the same library interface we do. This code is part of the GNU
- ! C Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- ! program understand `configure --with-gnu-libc' and omit the object
- ! files, it is simpler to just do this in the source for each such file. */
-
- ! #include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
- ! #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
- ! #include <gnu-versions.h>
- ! #if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
- ! #define ELIDE_CODE
- ! #endif
- ! #endif
- !
- !
- ! #ifndef ELIDE_CODE
-
-
- #if defined (__STDC__) && __STDC__
- --- 17,34 ----
-
- #include "obstack.h"
-
- ! /* This is just to get __GNU_LIBRARY__ defined. */
- ! #include <stdio.h>
-
- /* Comment out all this code if we are using the GNU C Library, and are not
- ! actually compiling the library itself. This code is part of the GNU C
- ! Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- ! program understand `configure --with-gnu-libc' and omit the object files,
- ! it is simpler to just do this in the source for each such file. */
-
- ! #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-
-
- #if defined (__STDC__) && __STDC__
- ***************
- *** 494,497 ****
-
- #endif /* 0 */
-
- ! #endif /* !ELIDE_CODE */
- --- 482,485 ----
-
- #endif /* 0 */
-
- ! #endif /* _LIBC or not __GNU_LIBRARY__. */
- diff -rNci gcc-2.7.2/optabs.c gcc-2.7.2p/optabs.c
- *** gcc-2.7.2/optabs.c Sat Oct 21 22:16:13 1995
- --- gcc-2.7.2p/optabs.c Thu Jun 15 11:55:15 1995
- ***************
- *** 3511,3517 ****
- /* The sign bit is not set. Convert as signed. */
- expand_float (target, from, 0);
- emit_jump_insn (gen_jump (label));
- - emit_barrier ();
-
- /* The sign bit is set.
- Convert to a usable (positive signed) value by shifting right
- --- 3511,3516 ----
- diff -rNci gcc-2.7.2/output.h gcc-2.7.2p/output.h
- *** gcc-2.7.2/output.h Fri Jul 14 12:02:05 1995
- --- gcc-2.7.2p/output.h Thu Jun 15 11:55:44 1995
- ***************
- *** 376,386 ****
-
- extern int current_function_varargs;
-
- - /* Nonzero if current function uses stdarg.h or equivalent.
- - Zero for functions that use varargs.h. */
- -
- - extern int current_function_stdarg;
- -
- /* Quantities of various kinds of registers
- used for the current function's args. */
-
- --- 376,381 ----
- diff -rNci gcc-2.7.2/print-rtl.c gcc-2.7.2p/print-rtl.c
- *** gcc-2.7.2/print-rtl.c Thu Jun 15 11:56:24 1995
- --- gcc-2.7.2p/print-rtl.c Tue Jan 23 09:25:29 1996
- ***************
- *** 231,236 ****
- --- 231,246 ----
- fprintf (stderr, "\n");
- }
-
- + void
- + tdebug_rtx(x, file)
- + rtx x;
- + FILE *file;
- + {
- + outfile=file;
- + print_rtx(x);
- + fprintf(file, "\n");
- + }
- +
- /* Count of rtx's to print with debug_rtx_list.
- This global exists because gdb user defined commands have no arguments. */
-
- diff -rNci gcc-2.7.2/real.c gcc-2.7.2p/real.c
- *** gcc-2.7.2/real.c Tue Aug 15 21:57:18 1995
- --- gcc-2.7.2p/real.c Thu Jun 15 11:57:39 1995
- ***************
- *** 2635,2647 ****
- unsigned EMUSHORT *a, *b, *c;
- {
- unsigned EMUSHORT ai[NI], bi[NI];
- ! int i, sign;
- EMULONG lt, lta, ltb;
-
- - /* IEEE says if result is not a NaN, the sign is "-" if and only if
- - operands have opposite signs -- but flush -0 to 0 later if not IEEE. */
- - sign = eisneg(a) ^ eisneg(b);
- -
- #ifdef NANS
- /* Return any NaN input. */
- if (eisnan (a))
- --- 2635,2643 ----
- unsigned EMUSHORT *a, *b, *c;
- {
- unsigned EMUSHORT ai[NI], bi[NI];
- ! int i;
- EMULONG lt, lta, ltb;
-
- #ifdef NANS
- /* Return any NaN input. */
- if (eisnan (a))
- ***************
- *** 2659,2665 ****
- || (eisinf (a) && eisinf (b)))
- {
- mtherr ("ediv", INVALID);
- ! enan (c, sign);
- return;
- }
- #endif
- --- 2655,2661 ----
- || (eisinf (a) && eisinf (b)))
- {
- mtherr ("ediv", INVALID);
- ! enan (c, eisneg (a) ^ eisneg (b));
- return;
- }
- #endif
- ***************
- *** 2667,2680 ****
- #ifdef INFINITY
- if (eisinf (b))
- {
- einfin (c);
- ! goto divsign;
- }
- /* Anything else over infinity is zero. */
- if (eisinf (a))
- {
- eclear (c);
- ! goto divsign;
- }
- #endif
- emovi (a, ai);
- --- 2663,2680 ----
- #ifdef INFINITY
- if (eisinf (b))
- {
- + if (eisneg (a) ^ eisneg (b))
- + *(c + (NE - 1)) = 0x8000;
- + else
- + *(c + (NE - 1)) = 0;
- einfin (c);
- ! return;
- }
- /* Anything else over infinity is zero. */
- if (eisinf (a))
- {
- eclear (c);
- ! return;
- }
- #endif
- emovi (a, ai);
- ***************
- *** 2692,2698 ****
- }
- }
- eclear (c);
- ! goto divsign;
- }
- dnzro1:
-
- --- 2692,2698 ----
- }
- }
- eclear (c);
- ! return;
- }
- dnzro1:
-
- ***************
- *** 2706,2716 ****
- goto dnzro2;
- }
- }
- /* Divide by zero is not an invalid operation.
- It is a divide-by-zero operation! */
- einfin (c);
- mtherr ("ediv", SING);
- ! goto divsign;
- }
- dnzro2:
-
- --- 2706,2720 ----
- goto dnzro2;
- }
- }
- + if (ai[0] == bi[0])
- + *(c + (NE - 1)) = 0;
- + else
- + *(c + (NE - 1)) = 0x8000;
- /* Divide by zero is not an invalid operation.
- It is a divide-by-zero operation! */
- einfin (c);
- mtherr ("ediv", SING);
- ! return;
- }
- dnzro2:
-
- ***************
- *** 2718,2735 ****
- /* calculate exponent */
- lt = ltb - lta + EXONE;
- emdnorm (bi, i, 0, lt, 64);
- ! emovo (bi, c);
- !
- ! divsign:
- !
- ! if (sign
- ! #ifndef IEEE
- ! && (ecmp (c, ezero) != 0)
- ! #endif
- ! )
- ! *(c+(NE-1)) |= 0x8000;
- else
- ! *(c+(NE-1)) &= ~0x8000;
- }
-
- /* Multiply e-types A and B, return e-type product C. */
- --- 2722,2733 ----
- /* calculate exponent */
- lt = ltb - lta + EXONE;
- emdnorm (bi, i, 0, lt, 64);
- ! /* set the sign */
- ! if (ai[0] == bi[0])
- ! bi[0] = 0;
- else
- ! bi[0] = 0Xffff;
- ! emovo (bi, c);
- }
-
- /* Multiply e-types A and B, return e-type product C. */
- ***************
- *** 2739,2751 ****
- unsigned EMUSHORT *a, *b, *c;
- {
- unsigned EMUSHORT ai[NI], bi[NI];
- ! int i, j, sign;
- EMULONG lt, lta, ltb;
-
- - /* IEEE says if result is not a NaN, the sign is "-" if and only if
- - operands have opposite signs -- but flush -0 to 0 later if not IEEE. */
- - sign = eisneg(a) ^ eisneg(b);
- -
- #ifdef NANS
- /* NaN times anything is the same NaN. */
- if (eisnan (a))
- --- 2737,2745 ----
- unsigned EMUSHORT *a, *b, *c;
- {
- unsigned EMUSHORT ai[NI], bi[NI];
- ! int i, j;
- EMULONG lt, lta, ltb;
-
- #ifdef NANS
- /* NaN times anything is the same NaN. */
- if (eisnan (a))
- ***************
- *** 2763,2769 ****
- || (eisinf (b) && (ecmp (a, ezero) == 0)))
- {
- mtherr ("emul", INVALID);
- ! enan (c, sign);
- return;
- }
- #endif
- --- 2757,2763 ----
- || (eisinf (b) && (ecmp (a, ezero) == 0)))
- {
- mtherr ("emul", INVALID);
- ! enan (c, eisneg (a) ^ eisneg (b));
- return;
- }
- #endif
- ***************
- *** 2771,2778 ****
- #ifdef INFINITY
- if (eisinf (a) || eisinf (b))
- {
- einfin (c);
- ! goto mulsign;
- }
- #endif
- emovi (a, ai);
- --- 2765,2776 ----
- #ifdef INFINITY
- if (eisinf (a) || eisinf (b))
- {
- + if (eisneg (a) ^ eisneg (b))
- + *(c + (NE - 1)) = 0x8000;
- + else
- + *(c + (NE - 1)) = 0;
- einfin (c);
- ! return;
- }
- #endif
- emovi (a, ai);
- ***************
- *** 2790,2796 ****
- }
- }
- eclear (c);
- ! goto mulsign;
- }
- mnzer1:
-
- --- 2788,2794 ----
- }
- }
- eclear (c);
- ! return;
- }
- mnzer1:
-
- ***************
- *** 2805,2811 ****
- }
- }
- eclear (c);
- ! goto mulsign;
- }
- mnzer2:
-
- --- 2803,2809 ----
- }
- }
- eclear (c);
- ! return;
- }
- mnzer2:
-
- ***************
- *** 2814,2831 ****
- /* calculate exponent */
- lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, 64);
- ! emovo (bi, c);
- !
- ! mulsign:
- !
- ! if (sign
- ! #ifndef IEEE
- ! && (ecmp (c, ezero) != 0)
- ! #endif
- ! )
- ! *(c+(NE-1)) |= 0x8000;
- else
- ! *(c+(NE-1)) &= ~0x8000;
- }
-
- /* Convert double precision PE to e-type Y. */
- --- 2812,2823 ----
- /* calculate exponent */
- lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, 64);
- ! /* calculate sign of product */
- ! if (ai[0] == bi[0])
- ! bi[0] = 0;
- else
- ! bi[0] = 0xffff;
- ! emovo (bi, c);
- }
-
- /* Convert double precision PE to e-type Y. */
- diff -rNci gcc-2.7.2/recog.c gcc-2.7.2p/recog.c
- *** gcc-2.7.2/recog.c Sat Jul 1 10:52:35 1995
- --- gcc-2.7.2p/recog.c Thu Jun 15 11:58:34 1995
- ***************
- *** 864,880 ****
- reg went on the stack.) */
- if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM)
- return general_operand (op, mode);
- -
- - #ifdef CLASS_CANNOT_CHANGE_SIZE
- - if (GET_CODE (SUBREG_REG (op)) == REG
- - && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER
- - && TEST_HARD_REG_BIT (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
- - REGNO (SUBREG_REG (op)))
- - && (GET_MODE_SIZE (mode)
- - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
- - return 0;
- - #endif
- -
- op = SUBREG_REG (op);
- }
-
- --- 864,869 ----
- diff -rNci gcc-2.7.2/reg-stack.c gcc-2.7.2p/reg-stack.c
- *** gcc-2.7.2/reg-stack.c Thu Jun 15 21:36:05 1995
- --- gcc-2.7.2p/reg-stack.c Tue Jan 23 09:25:29 1996
- ***************
- *** 230,235 ****
- --- 230,238 ----
- ((INSN_UID (INSN) > max_uid) \
- ? (abort() , -1) : block_number[INSN_UID (INSN)])
-
- + /* intel1 */
- + extern FILE *stack_reg_dump_file;
- +
- extern rtx forced_labels;
- extern rtx gen_jump ();
- extern rtx gen_movdf (), gen_movxf ();
- ***************
- *** 2121,2126 ****
- --- 2124,2131 ----
- replace_reg (dest, FIRST_STACK_REG);
- break;
-
- + /* intel1 */
- + case FLOAT_EXTEND:
- case REG:
- /* This is a `tstM2' case. */
- if (*dest != cc0_rtx)
- ***************
- *** 3131,3134 ****
- --- 3136,5348 ----
- fprintf (file, "\n");
- }
- }
- + /* intel1 */
- + #ifdef IS_STACK_MODE
- + #include "basic-block.h"
- + #include "obstack.h"
- + #define obstack_chunk_alloc xmalloc
- + #define obstack_chunk_free free
- +
- + extern int regset_bytes;
- + extern struct obstack momentary_obstack;
- + extern rtx *regno_reg_rtx;
- + extern int max_regno;
- +
- + static void func_stack_reg_to_stack_slot ();
- + static void bb_stack_reg_to_stack_slot ();
- + void float_to_int_cmp ();
- + static void offload_if_necessary ();
- + static void offload_reg ();
- + static void replace_with_stack_slot ();
- + static int stack_reg_dies_at_store ();
- + static void mark_stack_regs_mentioned ();
- + static void replace_with_temp_slot ();
- + static int reg_dead_at_pred ();
- + static int reg_only_set_or_stored ();
- + static int reg_used_in_body ();
- + static int store_into_temp ();
- + static int visit_till_dies ();
- + static int addr_or_val_changed ();
- + static void find_regs_mentioned ();
- + static int tests_equality ();
- + static int reg_last_loaded ();
- + static int reg_def_in_unvisited ();
- + static rtx reg_dies_in_block ();
- + static int death_blocks_ok ();
- +
- + /* For each basic block the union of the basic_block_live_at_start
- + of each of it's successors. */
- + regset *basic_block_maybe_live_at_end;
- +
- + /* To mark each block visited on a path */
- + char *blocks_visited;
- +
- + /* To mark those blocks on the path where the reg dies.
- + It is set to the NEXT_INSN of the insn in the block where
- + the reg dies */
- + rtx *death_blocks;
- +
- + /* To mark those blocks where the reg is defined */
- + char *blocks_defined;
- +
- + /* For finding block sucessors */
- + int *fall_thru_block, *jump_target_block;
- +
- + /* The temp slots allocated to stack regs */
- + rtx *reg_temp_slot;
- +
- + int num_visits;
- +
- + /* Information collected for optimizing use of stack regs
- + within a basic block
- + */
- + struct stack_reg_infos
- + {
- + rtx store_insn;
- + rtx non_dead_store[3];
- + rtx last_use;
- + unsigned char num_non_dead_store;
- + unsigned char dies_at_store;
- + }
- +
- + *stack_reg_info;
- +
- + static
- + struct regs_mentioned
- + {
- + rtx reg;
- + struct regs_mentioned *next;
- + } *reg_mentioned_header;
- +
- + void init_regset_vector ();
- +
- + void
- + opt_reg_stack ()
- + {
- +
- + reg_temp_slot = (rtx *) alloca (max_regno * sizeof (rtx));
- + bzero (reg_temp_slot, max_regno * sizeof (rtx));
- +
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file," MAX_REGNO at start %d\n",max_regno);
- + }
- + func_stack_reg_to_stack_slot ();
- + bb_stack_reg_to_stack_slot ();
- + #ifdef SPARE_REGS
- + max_regno = max_reg_num();
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file," MAX_REGNO at end %d\n",max_regno);
- + }
- + #endif
- + }
- +
- + /*
- + Stack mode registers that are used only to move values
- + in a basic block are replaced with stack slots.
- + We also have something like this for between basic blocks
- + see the ear spec agc()/earfilters.c the last loop
- + */
- + static void
- + bb_stack_reg_to_stack_slot ()
- + {
- + int block, nregs, stack_regno, num_calls;
- + rtx insn;
- +
- + nregs = max_regno;
- + stack_reg_info = (struct stack_reg_infos *)
- + alloca (nregs * sizeof (struct stack_reg_infos));
- +
- + for (block = 0; block < n_basic_blocks; block++)
- + {
- + bzero (stack_reg_info, nregs * sizeof (struct stack_reg_infos));
- + num_calls = 0;
- + for (insn = basic_block_end[block];
- + insn && insn != PREV_INSN (basic_block_head[block]);
- + insn = PREV_INSN (insn))
- + {
- + if (GET_CODE (insn) == CALL_INSN)
- + num_calls++;
- + if (GET_CODE (insn) == INSN)
- + {
- + if (GET_CODE (PATTERN (insn)) != SET)
- + {
- + if (GET_CODE (PATTERN (insn)) == PARALLEL)
- + {
- + if (flag_do_offload)
- + offload_if_necessary (insn, block);
- + }
- + bzero (stack_reg_info, nregs * sizeof (struct stack_reg_infos));
- + }
- + else
- + {
- + if (GET_CODE (SET_DEST (PATTERN (insn))) == REG
- + && GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
- + && GET_CODE (SET_SRC (PATTERN (insn))) == FLOAT_TRUNCATE)
- + {
- + rtx slot;
- + slot
- + = assign_stack_local (SFmode, GET_MODE_SIZE (SFmode), -1);
- + emit_insn_after (gen_rtx (SET, 0, SET_DEST (PATTERN (insn)),
- + slot), insn);
- + SET_DEST (PATTERN (insn)) = slot;
- + }
- + stack_regno = -1;
- + if (stack_reg_dies_at_store (insn, &stack_regno))
- + { /* A store of stack_regno at which it dies. */
- + stack_reg_info[stack_regno].dies_at_store = 1;
- + stack_reg_info[stack_regno].store_insn = insn;
- + stack_reg_info[stack_regno].num_non_dead_store = 0;
- + }
- + else if (stack_regno != -1)
- + {
- + /* Stored but not dead. */
- + stack_reg_info[stack_regno].num_non_dead_store++;
- + if (stack_reg_info[stack_regno].num_non_dead_store <= 3)
- + {
- + stack_reg_info[stack_regno].non_dead_store
- + [stack_reg_info[stack_regno].num_non_dead_store - 1]
- + = insn;
- + }
- + else
- + {
- + stack_reg_info[stack_regno].dies_at_store = 0;
- + stack_reg_info[stack_regno].store_insn = NULL;
- + stack_reg_info[stack_regno].last_use = NULL;
- + stack_reg_info[stack_regno].num_non_dead_store = 0;
- + }
- + }
- + else
- + mark_stack_regs_mentioned (SET_SRC (PATTERN (insn)), insn);
- + if (GET_CODE (SET_DEST (PATTERN (insn))) != REG)
- + mark_stack_regs_mentioned (SET_DEST (PATTERN (insn)), insn);
- + if (GET_CODE (SET_DEST (PATTERN (insn))) == REG
- + && IS_STACK_MODE (GET_MODE (SET_DEST (PATTERN (insn))))
- + )
- + { /* A setting of a stack register. */
- + if (((GET_CODE (SET_SRC (PATTERN (insn))) == MEM
- + && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn))))
- + || GET_CODE (SET_SRC (PATTERN (insn))) == CONST_DOUBLE)
- + && stack_reg_info[REGNO (SET_DEST (PATTERN (insn)))].dies_at_store)
- + { /* It is loaded from a non volatile memory and
- + was stored upon death later in the basic block,
- + try to do this NOT via the register stack. */
- + replace_with_stack_slot (insn, block, num_calls);
- + }
- + else
- + { /* Just try to optimize consecutive stores and
- + restart the information gathering.
- + */
- + stack_regno = REGNO (SET_DEST (PATTERN (insn)));
- + opt_consec_stores (stack_regno);
- + stack_reg_info[stack_regno].dies_at_store = 0;
- + stack_reg_info[stack_regno].store_insn = NULL;
- + stack_reg_info[stack_regno].last_use = NULL;
- + stack_reg_info[stack_regno].num_non_dead_store = 0;
- + }
- + }
- + }
- + }
- + }
- + }
- + }
- +
- + /*
- + Change
- + fst mem1
- + fstp mem2
- + to
- + fstp mem1
- + mov mem1,mem2
- + regno is the number of the stack register being stored.
- + */
- + opt_consec_stores (regno)
- + int regno;
- + {
- + rtx insn, note;
- +
- + if (stack_reg_info[regno].store_insn
- + && stack_reg_info[regno].dies_at_store
- + && stack_reg_info[regno].num_non_dead_store != 0
- + && stack_reg_info[regno].non_dead_store[0] ==
- + PREV_INSN (stack_reg_info[regno].store_insn))
- + {
- + insn = stack_reg_info[regno].store_insn;
- + SET_SRC (PATTERN (insn))
- + = copy_rtx (SET_DEST (PATTERN (stack_reg_info[regno].non_dead_store[0])));
- + if (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == PRE_DEC
- + || GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == PRE_INC)
- + {
- + XEXP (SET_SRC (PATTERN (insn)), 0) =
- + XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0);
- + }
- + INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
- + note = find_regno_note (insn, REG_DEAD, regno);
- + remove_note (insn, note);
- + if (!find_regno_note (stack_reg_info[regno].non_dead_store[0], REG_DEAD, regno))
- + {
- + REG_NOTES (stack_reg_info[regno].non_dead_store[0])
- + = gen_rtx (EXPR_LIST, REG_DEAD, regno_reg_rtx[regno],
- + REG_NOTES (stack_reg_info[regno].non_dead_store[0]));
- + }
- + }
- + }
- +
- +
- + /*
- + If the register being compared is the result of a computation in
- + this block, and the second comparison operand is not so, and it is
- + being compared for equality.
- + offload and reload it before the compare
- + The reason for this is that the stack registers are 80bit precision
- + and hence the comparison may fail due to precision.
- + */
- +
- + static void
- + offload_if_necessary (insn, blocknum)
- + rtx insn;
- + int blocknum;
- + {
- + rtx cmp_part, new_insn, last_set_insn, assign_stack_local ();
- + int regno;
- +
- + if (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
- + {
- + cmp_part = XVECEXP (PATTERN (insn), 0, 0);
- + last_set_insn = NULL;
- + if (SET_DEST (cmp_part) == cc0_rtx
- + && GET_CODE (SET_SRC (cmp_part)) == COMPARE
- + && GET_MODE (SET_SRC (cmp_part)) == CCmode)
- + {
- + if (GET_CODE (XEXP (SET_SRC (cmp_part), 0)) == REG
- + && GET_MODE (XEXP (SET_SRC (cmp_part), 0)) == DFmode
- + && GET_CODE (XEXP (SET_SRC (cmp_part), 1)) != REG
- + && !reg_last_loaded (blocknum, PREV_INSN (insn),
- + REGNO (XEXP (SET_SRC (cmp_part), 0)), &last_set_insn)
- + && last_set_insn
- + && tests_equality (NEXT_INSN (insn)))
- + {
- + regno = REGNO (XEXP (SET_SRC (cmp_part), 0));
- + if (reg_temp_slot[regno] == NULL)
- + {
- + reg_temp_slot[regno]
- + = assign_stack_local (GET_MODE (XEXP (SET_SRC (cmp_part), 0)),
- + GET_MODE_SIZE (GET_MODE (XEXP (SET_SRC (cmp_part), 0))),
- + -1);
- + }
- + MEM_VOLATILE_P (reg_temp_slot[regno]) = 1;
- + new_insn
- + = emit_insn_before (
- + gen_rtx (SET, 0,
- + reg_temp_slot[regno], XEXP (SET_SRC (cmp_part), 0)),
- + insn);
- + if (basic_block_head[blocknum] == insn)
- + {
- + basic_block_head[blocknum] = new_insn;
- + }
- + REG_NOTES (new_insn)
- + = gen_rtx (EXPR_LIST, REG_DEAD,
- + XEXP (SET_SRC (cmp_part), 0),
- + REG_NOTES (new_insn));
- + reg_n_deaths[regno]++;
- + emit_insn_before (
- + gen_rtx (SET, 0,
- + XEXP (SET_SRC (cmp_part), 0), reg_temp_slot[regno]),
- + insn);
- + }
- + }
- + }
- + }
- +
- +
- + /*
- + Return 1 if the insn which is a jump insn tests for equality or
- + inequality
- + else return 0
- + */
- +
- + static int
- + tests_equality (insn)
- + rtx insn;
- + {
- + if (GET_CODE (insn) == JUMP_INSN &&
- + GET_CODE (PATTERN (insn)) == SET &&
- + SET_DEST (PATTERN (insn)) == pc_rtx &&
- + GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE &&
- + (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == NE ||
- + GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == EQ))
- + {
- + return (1);
- + }
- + return (0);
- + }
- +
- +
- + /*
- + Search backward in block# blocknum, beginning at insn for a set of
- + reg# regno.
- + if found
- + set *last_set_insn to that set
- + if the source that sets regno is one of the desired sources
- + (see below) return 1
- + else return 0
- + else return 0
- + */
- + static int
- + reg_last_loaded (blocknum, insn, regno, last_set_insn)
- + int blocknum, regno;
- + rtx insn, *last_set_insn;
- + {
- + rtx last_set;
- + int found, i;
- +
- + last_set = insn;
- + found = 0;
- + while (!found && last_set != PREV_INSN (basic_block_head[blocknum]))
- + {
- + if (GET_CODE (last_set) == INSN)
- + {
- + if (GET_CODE (PATTERN (last_set)) == PARALLEL)
- + {
- + for (i = 0; i < XVECLEN (PATTERN (last_set), 0); i++)
- + {
- + if (GET_CODE (XVECEXP (PATTERN (last_set), 0, i)) == SET)
- + {
- + if (GET_CODE (SET_DEST (XVECEXP (PATTERN (last_set), 0, i))) == REG &&
- + REGNO (SET_DEST (XVECEXP (PATTERN (last_set), 0, i))) == regno)
- + {
- + *last_set_insn = last_set;
- + return (0);
- + }
- + }
- + else if (GET_CODE (XVECEXP (PATTERN (last_set), 0, i)) == CLOBBER)
- + {
- + if (GET_CODE (SET_DEST (XVECEXP (PATTERN (last_set), 0, i))) == REG &&
- + REGNO (SET_DEST (XVECEXP (PATTERN (last_set), 0, i))) == regno)
- + {
- + *last_set_insn = last_set;
- + return (0);
- + }
- + }
- + else
- + {
- + return (0);
- + }
- + }
- + }
- + if ((GET_CODE (PATTERN (last_set)) == SET ||
- + GET_CODE (PATTERN (last_set)) == CLOBBER) &&
- + GET_CODE (SET_DEST (PATTERN (last_set))) == REG &&
- + REGNO (SET_DEST (PATTERN (last_set))) == regno)
- + {
- + if (GET_CODE (PATTERN (last_set)) == CLOBBER)
- + {
- + *last_set_insn = last_set;
- + return (0);
- + }
- + if (GET_CODE (SET_SRC (PATTERN (last_set))) != MEM
- + && GET_CODE (SET_SRC (PATTERN (last_set))) != CONST_DOUBLE
- + && GET_CODE (SET_SRC (PATTERN (last_set))) != REG
- + && GET_CODE (SET_SRC (PATTERN (last_set))) != SUBREG
- + && GET_CODE (SET_SRC (PATTERN (last_set))) != FLOAT
- + && GET_CODE (SET_SRC (PATTERN (last_set))) != FLOAT_EXTEND)
- + {
- + *last_set_insn = last_set;
- + return (0);
- + }
- + else
- + {
- + *last_set_insn = last_set;
- + if (GET_CODE (SET_SRC (PATTERN (last_set))) == REG &&
- + REGNO (SET_SRC (PATTERN (last_set))) < FIRST_PSEUDO_REGISTER)
- + return (0);
- + return (1);
- + }
- + }
- + }
- + if (!found)
- + {
- + last_set = PREV_INSN (last_set);
- + }
- + }
- + return (0);
- + }
- +
- +
- + /*
- + insn loads a stack reg from memory and later on in the block
- + at stack_reg_info[REGNO(SET_DEST(PATTERN(insn)))].store_insn
- + that stack reg is stored into memory and marked as dead. Also
- + no insn between these two insns sets that stack reg.
- + This procedure changes the store from the register stack to
- + a store from the regular stack - which is faster.
- + */
- + static void
- + replace_with_stack_slot (insn, block_num, num_calls)
- + rtx insn;
- + int block_num, num_calls;
- + {
- + rtx note, stack_slot, store_insn, new_insn;
- + rtx notes_to_move, assign_stack_local ();
- + int i, regno, mem_possibly_changed;
- + char *storage;
- +
- + notes_to_move = NULL;
- + regno = REGNO (SET_DEST (PATTERN (insn)));
- + store_insn = stack_reg_info[regno].store_insn;
- + storage = (char *) obstack_alloc (&momentary_obstack, 0);
- +
- + /* Check if the memory being loaded into the stack register may
- + possibly change between insn and store_insn.
- + */
- + mem_possibly_changed
- + = (GET_CODE (SET_SRC (PATTERN (insn))) == CONST_DOUBLE) ? 0 :
- + addr_or_val_changed (SET_SRC (PATTERN (insn)), insn, store_insn);
- + obstack_free (&momentary_obstack, storage);
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + "Offload stack reg%d used only within basic block insn %d store_insn %d\n",
- + regno, INSN_UID (insn), INSN_UID (stack_reg_info[regno].store_insn));
- + if (stack_reg_info[regno].last_use != NULL)
- + {
- + fprintf (stack_reg_dump_file,
- + " reg used at insn %d\n",
- + INSN_UID (stack_reg_info[regno].last_use));
- + }
- + }
- + if (reg_temp_slot[regno] == NULL && mem_possibly_changed)
- + { /* Must allocate a stack slot */
- + #ifdef SPARE_REGS
- + if (max_reg_num () < max_regno)
- + {
- + if (GET_MODE (SET_DEST (PATTERN (insn))) == SFmode)
- + reg_temp_slot[regno] = gen_reg_rtx (SImode);
- + else
- + reg_temp_slot[regno]
- + = assign_stack_local (GET_MODE (SET_DEST (PATTERN (insn))),
- + GET_MODE_SIZE (GET_MODE (SET_DEST (PATTERN (insn)))),
- + -1);
- + }
- + else
- + #endif
- + reg_temp_slot[regno]
- + = assign_stack_local (GET_MODE (SET_DEST (PATTERN (insn))),
- + GET_MODE_SIZE (GET_MODE (SET_DEST (PATTERN (insn)))),
- + -1);
- + }
- + if (mem_possibly_changed)
- + /* Use the stack slot */
- + stack_slot = reg_temp_slot[regno];
- + else
- + /* The memory slot from which the stack register was loaded can be used */
- + stack_slot = SET_SRC (PATTERN (insn));
- + if (stack_reg_info[regno].last_use == NULL)
- + { /* The stack register was not used between the load and store */
- + if (mem_possibly_changed)
- + {
- + SET_DEST (PATTERN (insn)) = stack_slot;
- + if (GET_CODE (stack_slot) == REG)
- + {
- + if (GET_CODE (SET_SRC (PATTERN (insn)))
- + == CONST_DOUBLE)
- + {
- + SET_SRC (PATTERN (insn)) =
- + gen_rtx (CONST_INT, 0, CONST_DOUBLE_HIGH (SET_SRC (PATTERN (insn))));
- + }
- + else
- + {
- + PUT_MODE (SET_SRC (PATTERN (insn)), GET_MODE (stack_slot));
- + }
- + }
- + INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
- + }
- + else
- + {
- + PUT_CODE (insn, NOTE);
- + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (insn) = 0;
- + notes_to_move = REG_NOTES (insn);
- + }
- + }
- + else
- + { /* The stack register was also used in some computation */
- + if (mem_possibly_changed)
- + {
- + new_insn
- + = emit_insn_after (
- + gen_rtx (SET, 0, stack_slot, copy_rtx (SET_SRC (PATTERN (insn)))),
- + insn);
- + if (GET_CODE (stack_slot) == REG)
- + {
- + PUT_MODE (SET_SRC (PATTERN (new_insn)), GET_MODE (stack_slot));
- + }
- + INSN_CODE (new_insn) = recog (PATTERN (new_insn), new_insn, 0);
- + }
- + }
- + SET_SRC (PATTERN (store_insn)) = stack_slot;
- + if (GET_CODE (stack_slot) == REG )
- + {
- + reg_n_refs[REGNO (stack_slot)]++;
- + reg_n_sets[REGNO (stack_slot)]++;
- + reg_n_calls_crossed[REGNO (stack_slot)] = num_calls;
- + reg_n_deaths[REGNO (stack_slot)]++;
- + if (reg_basic_block[REGNO (stack_slot)] != -1)
- + {
- + reg_basic_block[REGNO (stack_slot)] = REG_BLOCK_GLOBAL;
- + }
- + else
- + {
- + reg_basic_block[REGNO (stack_slot)] = block_num;
- + }
- + PUT_MODE (SET_DEST (PATTERN (store_insn)), GET_MODE (stack_slot));
- + REG_NOTES (store_insn) =
- + gen_rtx (EXPR_LIST, REG_DEAD, stack_slot, REG_NOTES (store_insn));
- + }
- + INSN_CODE (store_insn) = recog (PATTERN (store_insn), store_insn, 0);
- + note = find_regno_note (store_insn, REG_DEAD, regno);
- + remove_note (store_insn, note);
- + if (notes_to_move)
- + { /* Maintain consistency of REG NOTE information */
- + rtx link, prev_link;
- + prev_link = REG_NOTES (store_insn);
- + for (link = REG_NOTES (store_insn); link; link = XEXP (link, 1))
- + {
- + prev_link = link;
- + }
- + if (prev_link)
- + {
- + XEXP (prev_link, 1) = notes_to_move;
- + }
- + else
- + {
- + REG_NOTES (store_insn) = notes_to_move;
- + }
- + }
- + if (stack_reg_info[regno].last_use == NULL)
- + {
- + reg_n_deaths[regno]--;
- + }
- + else if (!find_regno_note (stack_reg_info[regno].last_use, REG_DEAD, regno))
- + {
- + REG_NOTES (stack_reg_info[regno].last_use)
- + = gen_rtx (EXPR_LIST, REG_DEAD, regno_reg_rtx[regno],
- + REG_NOTES (stack_reg_info[regno].last_use));
- + }
- + for (i = 0;
- + i < (int) stack_reg_info[regno].num_non_dead_store;
- + i++)
- + { /* Handle the stores of the stack register that were done
- + between insn and store_insn. */
- + store_insn
- + = stack_reg_info[regno].non_dead_store[i];
- + SET_SRC (PATTERN (store_insn)) = stack_slot;
- + if (GET_CODE (stack_slot) == REG )
- + {
- + reg_n_refs[REGNO (stack_slot)]++;
- + PUT_MODE (SET_DEST (PATTERN (store_insn)), GET_MODE (stack_slot));
- + }
- + INSN_CODE (store_insn) = recog (PATTERN (store_insn), store_insn, 0);
- + }
- + stack_reg_info[regno].store_insn = NULL;
- + stack_reg_info[regno].last_use = NULL;
- + stack_reg_info[regno].num_non_dead_store = 0;
- + stack_reg_info[regno].dies_at_store = 0;
- + }
- +
- +
- +
- + /*
- + GET_CODE(mem) is MEM
- + we are interested in the insns between start_insn and stop_insn
- + (non inclusive)
- + return 1 if the address of mem or the contents of mem may POSSIBLY
- + be changed in this interval
- + return 0 otherwise
- + by address of mem changing we mean that mem contains a base and/or
- + index register and some insn in the interval sets the register.
- + */
- + static int
- + addr_or_val_changed (mem, start_insn, stop_insn)
- + rtx mem, start_insn, stop_insn;
- + {
- + rtx insn;
- + struct regs_mentioned *a_reg_mentioned;
- + char * storage;
- +
- + if (MEM_VOLATILE_P (mem))
- + {
- + return (1);
- + }
- + /*
- + if (RTX_UNCHANGING_P (mem))
- + {
- + return (0);
- + } */
- + reg_mentioned_header = NULL;
- + storage = (char *) obstack_alloc (&momentary_obstack, 0);
- + find_regs_mentioned (mem);
- + for (insn = NEXT_INSN (start_insn); insn != stop_insn; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == CODE_LABEL)
- + {
- + return (1);
- + }
- + if (GET_CODE (insn) == INSN)
- + {
- + if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == CLOBBER)
- + {
- + if (GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
- + {
- + if (true_dependence (mem, SET_DEST (PATTERN (insn))))
- + {
- + obstack_free (&momentary_obstack, storage);
- + return (1);
- + }
- + }
- + else if (GET_CODE (SET_DEST (PATTERN (insn))) == REG)
- + {
- + for (a_reg_mentioned = reg_mentioned_header;
- + a_reg_mentioned != NULL;
- + a_reg_mentioned = a_reg_mentioned->next)
- + {
- + if (reg_overlap_mentioned_p (SET_DEST (PATTERN (insn)),
- + a_reg_mentioned->reg)
- + )
- + {
- + obstack_free (&momentary_obstack, storage);
- + return (1);
- + }
- + }
- + }
- + else
- + {
- + obstack_free (&momentary_obstack, storage);
- + return (1);
- + }
- + }
- + else
- + {
- + obstack_free (&momentary_obstack, storage);
- + return (1);
- + }
- + }
- + }
- + obstack_free (&momentary_obstack, storage);
- + return (0);
- + }
- +
- +
- + /* Build a linked list of (struct regs_mentioned) describing the
- + registers used in the pattern pat.
- + */
- + static void
- + find_regs_mentioned (pat)
- + rtx pat;
- + {
- + register char *fmt;
- + register int i;
- + register enum rtx_code code;
- + struct regs_mentioned *one_reg;
- +
- + code = GET_CODE (pat);
- +
- + switch (code)
- + {
- + case REG:
- + one_reg = (struct regs_mentioned *)
- + obstack_alloc (&momentary_obstack, sizeof (struct regs_mentioned));
- + one_reg->reg = pat;
- + one_reg->next = reg_mentioned_header;
- + reg_mentioned_header = one_reg;
- + return;
- +
- + /* These codes have no constituent expressions
- + and are unique. */
- + case SCRATCH:
- + case CC0:
- + case PC:
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + return;
- +
- +
- + }
- +
- +
- + fmt = GET_RTX_FORMAT (code);
- +
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + {
- + if (fmt[i] == 'E')
- + {
- + register int j;
- + for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
- + find_regs_mentioned (XVECEXP (pat, i, j));
- + }
- + else if (fmt[i] == 'e')
- + find_regs_mentioned (XEXP (pat, i));
- + }
- + }
- +
- +
- + /*
- + if insn stores a stack register into memory
- + set *regno to the register# stored
- + if the stack register is marked dead at the store
- + return 1
- + else
- + return 0
- + */
- + static int
- + stack_reg_dies_at_store (insn, regno)
- + rtx insn;
- + int *regno;
- + {
- + if (GET_CODE (SET_DEST (PATTERN (insn))) == MEM
- + && GET_CODE (SET_SRC (PATTERN (insn))) == REG
- + && IS_STACK_MODE (GET_MODE (SET_SRC (PATTERN (insn))))
- + )
- + {
- + *regno = REGNO (SET_SRC (PATTERN (insn)));
- + return ((int) find_regno_note (insn, REG_DEAD, *regno));
- + }
- + return (0);
- + }
- +
- +
- + /*
- + Record relevant information on each stack register that is mentioned
- + in pat which is a subexpression of insn.
- + */
- + static void
- + mark_stack_regs_mentioned (pat, insn)
- + rtx pat, insn;
- + {
- + register char *fmt;
- + register int i;
- + register enum rtx_code code;
- +
- + code = GET_CODE (pat);
- +
- + switch (code)
- + {
- + case REG:
- + if (IS_STACK_MODE (GET_MODE (pat)))
- + {
- + if (stack_reg_info[REGNO (pat)].last_use == NULL)
- + {
- + stack_reg_info[REGNO (pat)].last_use = insn;
- + }
- + }
- + return;
- +
- + /* These codes have no constituent expressions
- + and are unique. */
- + case SCRATCH:
- + case CC0:
- + case PC:
- + case QUEUED:
- + case CONST_INT:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + case CODE_LABEL:
- + return;
- +
- +
- + }
- +
- +
- + fmt = GET_RTX_FORMAT (code);
- +
- + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- + {
- + if (fmt[i] == 'E')
- + {
- + register int j;
- + for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
- + mark_stack_regs_mentioned (XVECEXP (pat, i, j), insn);
- + }
- + else if (fmt[i] == 'e')
- + mark_stack_regs_mentioned (XEXP (pat, i), insn);
- + }
- + }
- +
- +
- + /*
- + Stack mode registers that are set in one basic block and only
- + loaded to or stored from in successor blocks are replaced with
- + stack slots in the successor blocks.
- + */
- + static void
- + func_stack_reg_to_stack_slot ()
- + {
- + rtx head, tail, target;
- + register regset tem;
- + int i, j, found, target_blocknum, regno, successful_visit, reg_defined_elsewhere,
- + reg_set_or_stored, cmprd, only_cmp;
- + char *storage;
- + #ifdef SPARE_REGS
- + int max_regno = max_reg_num ();
- + #endif
- +
- +
- + storage = (char *) obstack_alloc (&momentary_obstack, 0);
- + basic_block_maybe_live_at_end = (regset *) alloca (n_basic_blocks * sizeof (regset));
- + tem = (regset) obstack_alloc (&momentary_obstack, n_basic_blocks * regset_bytes);
- + bzero (tem, n_basic_blocks * regset_bytes);
- + init_regset_vector (basic_block_maybe_live_at_end, tem, n_basic_blocks, regset_bytes);
- + jump_target_block = (int *) alloca (n_basic_blocks * sizeof (int));
- + fall_thru_block = (int *) alloca (n_basic_blocks * sizeof (int));
- + blocks_visited = (char *) alloca (n_basic_blocks * sizeof (char));
- + death_blocks = (rtx *) alloca (n_basic_blocks * sizeof (rtx));
- + blocks_defined = (char *) alloca (n_basic_blocks * sizeof (char));
- + cmprd = 0;
- + only_cmp = 1;
- +
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + "Offload stack regs:\n\n");
- + }
- + /* Find block successors */
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + jump_target_block[i] = -1;
- + fall_thru_block[i] = -1;
- + head = basic_block_head[i];
- + tail = basic_block_end[i];
- + if (GET_CODE (tail) == JUMP_INSN)
- + {
- + target = JUMP_LABEL (tail);
- + if (target == NULL)
- + {
- + return;
- + }
- + /* target is the head of the basic block jumped to
- + find which block it is */
- + target_blocknum = 0;
- + found = 0;
- + while (target_blocknum < n_basic_blocks && !found)
- + {
- + if (basic_block_head[target_blocknum] == target)
- + {
- + found = 1;
- + }
- + else
- + {
- + target_blocknum++;
- + }
- + }
- + if (!found)
- + {
- + return;
- + }
- + jump_target_block[i] = target_blocknum;
- + for (j = 0; j < regset_size; j++)
- + basic_block_maybe_live_at_end[i][j]
- + |= basic_block_live_at_start[target_blocknum][j];
- + }
- + if (!simplejump_p (tail))
- + {
- + if (i < n_basic_blocks - 1)
- + {
- + fall_thru_block[i] = i + 1;
- + for (j = 0; j < regset_size; j++)
- + basic_block_maybe_live_at_end[i][j]
- + |= basic_block_live_at_start[i + 1][j];
- + }
- + }
- + }
- + if (stack_reg_dump_file)
- + my_dump_block_info ();
- + /* Do inter block optimizations */
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + for (regno = FIRST_PSEUDO_REGISTER; regno < max_regno; regno++)
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register int bit = 1 << (regno % REGSET_ELT_BITS);
- + if (stack_reg_dump_file
- + && IS_STACK_MODE (GET_MODE (regno_reg_rtx[regno]))
- + && (basic_block_maybe_live_at_end[i][offset] & bit)
- + && !(basic_block_live_at_start[i][offset] & bit)
- + )
- + {
- + fprintf (stack_reg_dump_file,
- + "\nstack reg%d in block %d d_a_p %d\n",
- + regno, i,
- + reg_dead_at_pred (offset, bit, i));
- + }
- + if ((basic_block_maybe_live_at_end[i][offset] & bit)
- + && reg_dead_at_pred (offset, bit, i)
- + && !(basic_block_live_at_start[i][offset] & bit)
- + && IS_STACK_MODE (GET_MODE (regno_reg_rtx[regno])))
- + {
- + /* A stack register that is live at the exit of the
- + block and not live on entry */
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + "\nstack reg%d in block %d live at end but not at start\n",
- + regno, i);
- + }
- + bzero (blocks_visited, n_basic_blocks * sizeof (char));
- + bzero (death_blocks, n_basic_blocks * sizeof (rtx));
- + num_visits = 0;
- + successful_visit = visit_till_dies (regno, i);
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file, " blocks visited : ");
- + for (j = 0; j < n_basic_blocks; j++)
- + {
- + if (blocks_visited[j])
- + {
- + fprintf (stack_reg_dump_file, "%d ", j);
- + }
- + }
- + fprintf (stack_reg_dump_file, "\n");
- + }
- + successful_visit =
- + successful_visit && death_blocks_ok (regno);
- + bzero (blocks_defined, n_basic_blocks * sizeof (char));
- + blocks_defined[i] = 1;
- + reg_defined_elsewhere = reg_def_in_unvisited (offset, bit, i);
- + reg_set_or_stored
- + = reg_only_set_or_stored (regno, i, &cmprd, &only_cmp);
- + if (successful_visit
- + && !reg_defined_elsewhere
- + && reg_set_or_stored)
- + { /* This reg was never used in any computation after
- + this set until it's death - so don't keep
- + it in stack reg after block i. Allocate a temp slot
- + for it and store it there at the end of block i.
- + In all visited blocks replace regno with this
- + temp slot. */
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + " only loaded or stored in all visited blocks\n");
- + }
- + if (store_into_temp (regno, i))
- + {
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + " replaced by temp slot in all blocks visited\n");
- + }
- + replace_with_temp_slot (regno, i);
- + }
- + }
- + else if (successful_visit && cmprd)
- + {
- + /* In each block where regno is defined by a computation
- + store it and reload it to avoid precision problems
- + in comparison */
- + offload_reg (regno);
- + }
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + " successful visit %d cmprd %d\n", successful_visit, cmprd);
- + }
- + }
- + }
- + }
- + obstack_free (&momentary_obstack, storage);
- + }
- +
- +
- + /*
- + The blocks where the stack reg dies on the visit have been
- + marked by death_blocks[block_num] being set to the NEXT_INSN
- + of the insn where it dies in the block.
- + For each of these blocks either the register must not be redefined
- + in the block or none of the successors of the block have been
- + visited.
- + */
- +
- + static int
- + death_blocks_ok (regno)
- + int regno;
- + {
- + int i, successor_visited;
- +
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + if (death_blocks[i])
- + {
- + successor_visited = 0;
- + if (fall_thru_block[i] != -1
- + && blocks_visited[fall_thru_block[i]])
- + {
- + successor_visited = 1;
- + }
- + if (successor_visited == 0 && jump_target_block[i] != -1
- + && blocks_visited[jump_target_block[i]])
- + {
- + successor_visited = 1;
- + }
- + if (successor_visited == 0)
- + {
- + continue;
- + }
- + else if (reg_set_between_p (regno_reg_rtx[regno],
- + PREV_INSN (death_blocks[i]),
- + NEXT_INSN (basic_block_end[i])))
- + {
- + return (0);
- + }
- + }
- + }
- + return (1);
- + }
- +
- +
- + /*
- + Like offload_if_necessary but for stack registers used in equality
- + comparisons in one basic block and computed in another. The offload
- + and reload are done at the place of computation.
- + */
- + static void
- + offload_reg (regno)
- + int regno;
- + {
- + int block, reg_loaded;
- + rtx last_set_insn, new_insn;
- +
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + "offload compared reg %d\n", regno);
- + }
- + for (block = 0; block < n_basic_blocks; block++)
- + {
- + if (blocks_defined[block])
- + {
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + " defined in block %d\n", block);
- + }
- + last_set_insn = NULL;
- + reg_loaded
- + = reg_last_loaded (block, basic_block_end[block], regno, &last_set_insn);
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + " reg loaded %d ", reg_loaded);
- + if (last_set_insn)
- + fprintf (stack_reg_dump_file,
- + " last_set_insn %d", INSN_UID (last_set_insn));
- + fprintf (stack_reg_dump_file, "\n");
- + }
- + if (reg_loaded == 0 && last_set_insn)
- + {
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + " actually offloading\n");
- + }
- + if (reg_temp_slot[regno] == NULL)
- + {
- + reg_temp_slot[regno]
- + = assign_stack_local (GET_MODE (regno_reg_rtx[regno]),
- + GET_MODE_SIZE (GET_MODE (regno_reg_rtx[regno])),
- + -1);
- + }
- + MEM_VOLATILE_P (reg_temp_slot[regno]) = 1;
- + new_insn
- + = emit_insn_before (
- + gen_rtx (SET, 0,
- + reg_temp_slot[regno], regno_reg_rtx[regno]),
- + NEXT_INSN (last_set_insn));
- + REG_NOTES (new_insn)
- + = gen_rtx (EXPR_LIST, REG_DEAD,
- + regno_reg_rtx[regno],
- + REG_NOTES (new_insn));
- + reg_n_deaths[regno]++;
- + new_insn
- + = emit_insn_before (
- + gen_rtx (SET, 0,
- + regno_reg_rtx[regno], reg_temp_slot[regno]),
- + NEXT_INSN (new_insn));
- + if (basic_block_end[block] == last_set_insn)
- + {
- + basic_block_end[block] = new_insn;
- + }
- + }
- + }
- + }
- + }
- +
- + /*
- + If the reg given by offset an bit in the live vecotrs is not live
- + at the end of any blocks that are the predecessors of blocknum
- + (except blocknum itself)
- + return 1
- + else
- + return 0
- + */
- + static int
- + reg_dead_at_pred (offset, bit, blocknum)
- + int offset, bit, blocknum;
- + {
- + rtx head, jump;
- + int i;
- +
- + head = basic_block_head[blocknum];
- +
- + if (GET_CODE (head) == CODE_LABEL)
- + for (jump = LABEL_REFS (head);
- + jump != head;
- + jump = LABEL_NEXTREF (jump))
- + {
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + if (basic_block_end[i] == CONTAINING_INSN (jump))
- + break;
- + }
- + if (i == n_basic_blocks)
- + {
- + return (0);
- + }
- + if (i != blocknum)
- + {
- + if (basic_block_maybe_live_at_end[i][offset] & bit)
- + {
- + return (0);
- + }
- + }
- + }
- +
- + if ((blocknum - 1) == -1 ||
- + simplejump_p (basic_block_end[blocknum - 1]) ||
- + !(basic_block_maybe_live_at_end[blocknum - 1][offset] & bit))
- + {
- + return (1);
- + }
- + return (0);
- +
- + }
- +
- + /*
- + If the definition of the register in some visited block is
- + done by a block that has not been visited then return 1
- + */
- + static int
- + reg_def_in_unvisited (offset, bit, blocknum)
- + int offset, bit, blocknum;
- + {
- + int i, j, ret_val;
- + rtx head, jump;
- +
- + ret_val = 0;
- +
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + if (i != blocknum && blocks_visited[i])
- + {
- + head = basic_block_head[i];
- +
- + if (GET_CODE (head) == CODE_LABEL)
- + for (jump = LABEL_REFS (head);
- + jump != head;
- + jump = LABEL_NEXTREF (jump))
- + {
- + for (j = 0; j < n_basic_blocks; j++)
- + {
- + if (basic_block_end[j] == CONTAINING_INSN (jump))
- + break;
- + }
- + if (j == n_basic_blocks)
- + {
- + ret_val = 1;
- + }
- + if (blocks_visited[j] == 0 && j != i)
- + {
- + if (basic_block_maybe_live_at_end[j][offset] & bit)
- + {
- + blocks_defined[j] = 1;
- + ret_val = 1;
- + }
- + }
- + }
- +
- + if ((i - 1) != -1
- + && !simplejump_p (basic_block_end[i - 1])
- + && blocks_visited[i - 1] == 0
- + && basic_block_maybe_live_at_end[i - 1][offset] & bit)
- + {
- + blocks_defined[i - 1] = 1;
- + ret_val = 1;
- + }
- + }
- + }
- + return (ret_val);
- + }
- +
- +
- + /* regno is never used in any computation from it's set in
- + source_blocknum until it's death - so don't keep
- + it in stack reg after source_blocknum. Allocate a temp slot
- + for it and store it there at the end of block source_blocknum.
- + In all visited blocks replace regno with this temp slot.
- + In blocks where regno dies the replacement is done
- + up until the insn in which regno dies.
- + */
- + static void
- + replace_with_temp_slot (regno, source_blocknum)
- + {
- + int i, had_call, num_insns;
- + rtx insn, note;
- + register int offset = regno / REGSET_ELT_BITS;
- + register int bit = 1 << (regno % REGSET_ELT_BITS);
- + register int compl_bit;
- +
- + compl_bit = ~bit;
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + if (blocks_visited[i] && i != source_blocknum)
- + {
- + basic_block_live_at_start[i][offset] &= compl_bit;
- + if (!death_blocks[i])
- + {
- + basic_block_maybe_live_at_end[i][offset] &= compl_bit;
- + }
- + had_call = 0;
- + num_insns = 0;
- + for (insn = basic_block_head[i];
- + insn && insn != death_blocks[i]
- + && insn != NEXT_INSN (basic_block_end[i]);
- + insn = NEXT_INSN (insn))
- + {
- + num_insns++;
- + if (GET_CODE (insn) == CALL_INSN)
- + had_call = 1;
- + if (GET_CODE (insn) == INSN)
- + {
- + init_undo_buf ();
- + subst_in_insn (insn, PATTERN (insn), regno_reg_rtx[regno],
- + reg_temp_slot[regno], 0, 0);
- + if (GET_CODE (reg_temp_slot[regno]) == REG
- + && GET_CODE (PATTERN (insn)) == SET)
- + {
- + register int n_offset =
- + REGNO (reg_temp_slot[regno]) / REGSET_ELT_BITS;
- + register REGSET_ELT_TYPE n_bit
- + = (REGSET_ELT_TYPE) 1
- + << (REGNO (reg_temp_slot[regno]) % REGSET_ELT_BITS);
- + basic_block_live_at_start[i][n_offset] |= n_bit;
- + reg_basic_block[REGNO (reg_temp_slot[regno])] = REG_BLOCK_GLOBAL;
- + if (rtx_equal_p (reg_temp_slot[regno],
- + SET_DEST (PATTERN (insn))))
- + {
- + reg_n_sets[REGNO (reg_temp_slot[regno])]++;
- + reg_n_refs[REGNO (reg_temp_slot[regno])]++;
- + if (GET_CODE (SET_SRC (PATTERN (insn)))
- + == CONST_DOUBLE)
- + {
- + union
- + {
- + int i[2];
- + double d;
- + }
- + u1;
- + union
- + {
- + int i;
- + float f;
- + }
- + u2;
- + u1.i[0] =
- + CONST_DOUBLE_LOW (SET_SRC (PATTERN (insn)));
- + u1.i[1] =
- + CONST_DOUBLE_HIGH (SET_SRC (PATTERN (insn)));
- + u2.f = u1.d;
- + SET_SRC (PATTERN (insn)) =
- + gen_rtx (CONST_INT, 0, u2.i);
- + }
- + else
- + {
- + PUT_MODE (SET_SRC (PATTERN (insn)),
- + GET_MODE (reg_temp_slot[regno]));
- +
- + }
- + }
- + if (rtx_equal_p (reg_temp_slot[regno],
- + SET_SRC (PATTERN (insn))))
- + {
- + PUT_MODE (SET_DEST (PATTERN (insn)),
- + GET_MODE (reg_temp_slot[regno]));
- + reg_live_length[REGNO (reg_temp_slot[regno])]
- + += num_insns;
- + reg_n_refs[REGNO (reg_temp_slot[regno])]++;
- + if (had_call)
- + {
- + reg_n_calls_crossed[REGNO (reg_temp_slot[regno])]++;
- + }
- + }
- + }
- + INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
- + if ((note = find_regno_note (insn, REG_DEAD, regno)) != NULL)
- + {
- + if (GET_CODE (reg_temp_slot[regno]) == REG)
- + {
- + XEXP (note, 0) = reg_temp_slot[regno];
- + reg_n_deaths[REGNO (reg_temp_slot[regno])]++;
- + }
- + else
- + remove_note (insn, note);
- + }
- + }
- + }
- + }
- + }
- + }
- +
- +
- +
- + /*
- + If in each block_visited (except source_blocknum) regno is only
- + set, or used as a source in a store then
- + return 1
- + else
- + return 0
- + *used_in_cmp is set to 1 if regno is used in a comparison
- + in a block and it was not last set by a load before that
- + comparison
- + *only_cmp is set to 1 if the only other use of regno besides
- + as a dest or source of a store is in comparison, otherwise it
- + is set to 0
- + */
- + static int
- + reg_only_set_or_stored (regno, source_blocknum, used_in_cmp, only_cmp)
- + int regno, source_blocknum, *used_in_cmp, *only_cmp;
- + {
- + int i, ret_val;
- + rtx insn, cmp_part, last_set_insn;
- +
- + ret_val = 1;
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + if (blocks_visited[i] && i != source_blocknum)
- + {
- + for (insn = basic_block_head[i];
- + insn && insn != death_blocks[i]
- + && insn != NEXT_INSN (basic_block_end[i]);
- + insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN)
- + {
- + if (reg_used_in_body (regno, PATTERN (insn)))
- + {
- + ret_val = 0;
- + if (stack_reg_dump_file)
- + {
- + fprintf (stack_reg_dump_file,
- + " reg used in body of insn %d\n", INSN_UID (insn));
- + }
- + if (GET_CODE (PATTERN (insn)) == PARALLEL
- + && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
- + {
- + cmp_part = XVECEXP (PATTERN (insn), 0, 0);
- + last_set_insn = NULL;
- + if (SET_DEST (cmp_part) == cc0_rtx
- + && GET_CODE (SET_SRC (cmp_part)) == COMPARE
- + && (GET_MODE (SET_SRC (cmp_part)) == CCmode
- + || GET_MODE (SET_SRC (cmp_part)) == CCFPEQmode
- + || GET_MODE (SET_SRC (cmp_part)) == VOIDmode)
- + && GET_CODE (XEXP (SET_SRC (cmp_part), 0)) == REG
- + && REGNO (XEXP (SET_SRC (cmp_part), 0)) == regno
- + && (GET_CODE (XEXP (SET_SRC (cmp_part), 1)) != REG
- + || GET_MODE (SET_SRC (cmp_part)) == CCFPEQmode)
- + && !reg_last_loaded (i, PREV_INSN (insn),
- + REGNO (XEXP (SET_SRC (cmp_part), 0)),
- + &last_set_insn)
- + && !last_set_insn
- + && tests_equality (NEXT_INSN (insn)))
- + {
- + *used_in_cmp = 1;
- + }
- + else
- + {
- + *only_cmp = 0;
- + }
- + }
- + else
- + {
- + *only_cmp = 0;
- + }
- + }
- + }
- + }
- + }
- + }
- + return (ret_val);
- + }
- +
- + /*
- + If regno is used in insn is anyway except as a dest or source of a set
- + return 1
- + else
- + return 0
- + */
- + static int
- + reg_used_in_body (regno, body)
- + int regno;
- + rtx body;
- + {
- + int i, ret_val = 0;
- +
- + if (GET_CODE (body) == SET)
- + {
- + if (GET_CODE (SET_DEST (body)) != REG)
- + {
- + if (reg_overlap_mentioned_p (regno_reg_rtx[regno],
- + SET_DEST (body)))
- + {
- + return (1);
- + }
- + }
- + else if (REGNO (SET_DEST (body)) == regno)
- + {
- + if (GET_CODE (SET_SRC (body)) != MEM
- + && GET_CODE (SET_SRC (body)) != REG
- + && GET_CODE (SET_SRC (body)) != CONST_DOUBLE)
- + {
- + return (1);
- + }
- + }
- +
- + if (GET_CODE (SET_SRC (body)) != REG)
- + {
- + if (reg_overlap_mentioned_p (regno_reg_rtx[regno],
- + SET_SRC (body)))
- + {
- + return (1);
- + }
- + }
- + else if (REGNO (SET_SRC (body)) == regno)
- + {
- + if (/*GET_CODE (SET_DEST (body)) != REG
- + && */ GET_CODE (SET_DEST (body)) != MEM)
- + {
- + return (1);
- + }
- + }
- + return (0);
- + }
- + else if (GET_CODE (body) == CLOBBER)
- + {
- + if (GET_CODE (SET_DEST (body)) == REG && REGNO (SET_DEST (body)) == regno)
- + {
- + return (1);
- + }
- + return (0);
- + }
- + else if (GET_CODE (body) == PARALLEL)
- + {
- + for (i = 0; i < XVECLEN (body, 0); i++)
- + {
- + ret_val |= reg_used_in_body (regno, XVECEXP (body, 0, i));
- + if (ret_val)
- + {
- + return (1);
- + }
- + }
- + return (ret_val);
- + }
- + else
- + {
- + return (1);
- + }
- + }
- +
- + /*
- + If the stack reg regno has not already been allocated a temp slot then
- + allocate one for it.
- + Store the last value of regno in block# source_blocknum into it's
- + temp_slot.
- + Mark the last use of regno in the block as REG_DEAD
- + */
- + static int
- + store_into_temp (regno, source_blocknum)
- + int regno, source_blocknum;
- + {
- + rtx last_set, last_use, stack_slot, store_rtx, store_insn, note;
- + int found, insn_code_num, i;
- + register int offset;
- + register int bit;
- + register int compl_bit;
- +
- +
- + /* Find where regno is last set in source_blocknum */
- + last_set = basic_block_end[source_blocknum];
- + found = 0;
- + while (!found && last_set != PREV_INSN (basic_block_head[source_blocknum]))
- + {
- + if (GET_CODE (last_set) == INSN)
- + {
- + if (GET_CODE (PATTERN (last_set)) == PARALLEL)
- + {
- + for (i = 0; i < XVECLEN (PATTERN (last_set), 0); i++)
- + {
- + if (GET_CODE (XVECEXP (PATTERN (last_set), 0, i)) == SET)
- + {
- + if (GET_CODE (SET_DEST (XVECEXP (PATTERN (last_set), 0, i))) == REG &&
- + REGNO (SET_DEST (XVECEXP (PATTERN (last_set), 0, i))) == regno)
- + {
- + return (0);
- + }
- + }
- + else if (GET_CODE (XVECEXP (PATTERN (last_set), 0, i)) == CLOBBER)
- + {
- + if (GET_CODE (SET_DEST (XVECEXP (PATTERN (last_set), 0, i))) == REG &&
- + REGNO (SET_DEST (XVECEXP (PATTERN (last_set), 0, i))) == regno)
- + {
- + return (0);
- + }
- + }
- + else
- + {
- + return (0);
- + }
- + }
- + }
- + if ((GET_CODE (PATTERN (last_set)) == SET ||
- + GET_CODE (PATTERN (last_set)) == CLOBBER) &&
- + GET_CODE (SET_DEST (PATTERN (last_set))) == REG &&
- + REGNO (SET_DEST (PATTERN (last_set))) == regno)
- + {
- + if (GET_CODE (PATTERN (last_set)) == CLOBBER)
- + return (0);
- + if (GET_CODE (SET_SRC (PATTERN (last_set))) != MEM)
- + return (0);
- + found = 1;
- + }
- + }
- + if (!found)
- + {
- + last_set = PREV_INSN (last_set);
- + }
- + }
- + if (!found)
- + {
- + return (0);
- + }
- +
- +
- + /* Allocate a temp slot and store the value that is loaded into
- + regno at last_set into that temp slot and place the insn to
- + do this right after the load to regno */
- + if (reg_temp_slot[regno] == NULL)
- + {
- + #ifdef SPARE_REGS
- + if (max_reg_num () < max_regno)
- + {
- + if (GET_MODE (SET_DEST (PATTERN (last_set))) == SFmode)
- + {
- + reg_temp_slot[regno] = gen_reg_rtx (SImode);
- + }
- + else
- + reg_temp_slot[regno]
- + = assign_stack_local (GET_MODE (SET_DEST (PATTERN (last_set))),
- + GET_MODE_SIZE (GET_MODE (SET_DEST (PATTERN (last_set)))),
- + -1);
- + }
- + else
- + #endif
- + reg_temp_slot[regno]
- + = assign_stack_local (GET_MODE (SET_DEST (PATTERN (last_set))),
- + GET_MODE_SIZE (GET_MODE (SET_DEST (PATTERN (last_set)))),
- + -1);
- + }
- + store_rtx = gen_rtx (SET, 0, reg_temp_slot[regno],
- + copy_rtx (SET_SRC (PATTERN (last_set))));
- + if (GET_CODE (reg_temp_slot[regno]) == REG )
- + {
- + if (GET_CODE (SET_SRC (store_rtx)) == CONST_DOUBLE)
- + {
- + union
- + {
- + int i[2];
- + double d;
- + }
- + u1;
- + union
- + {
- + int i;
- + float f;
- + }
- + u2;
- + u1.i[0] = CONST_DOUBLE_LOW (SET_SRC (store_rtx));
- + u1.i[1] = CONST_DOUBLE_HIGH (SET_SRC (store_rtx));
- + u2.f = u1.d;
- + SET_SRC (store_rtx) =
- + gen_rtx (CONST_INT, 0, u2.i);
- + }
- + else
- + {
- + PUT_MODE (SET_SRC (store_rtx), GET_MODE (reg_temp_slot[regno]));
- + }
- + reg_n_sets[REGNO (reg_temp_slot[regno])]++;
- + reg_n_refs[REGNO (reg_temp_slot[regno])]++;
- + reg_live_length[REGNO (reg_temp_slot[regno])] = 2;
- + }
- + insn_code_num = recog (store_rtx, last_set);
- + if (insn_code_num < 0)
- + {
- + return (0);
- + }
- + store_insn = emit_insn_after (store_rtx, PREV_INSN (last_set));
- + INSN_CODE (store_insn) = insn_code_num;
- +
- + /* Find where regno is last use in source_blocknum */
- + last_use = basic_block_end[source_blocknum];
- + found = 0;
- + while (!found && last_use != PREV_INSN (basic_block_head[source_blocknum]))
- + {
- + if (GET_CODE (last_use) == INSN)
- + {
- + if (reg_overlap_mentioned_p (regno_reg_rtx[regno], PATTERN (last_use)))
- + {
- + found = 1;
- + }
- + }
- + if (!found)
- + {
- + last_use = PREV_INSN (last_use);
- + }
- + }
- + offset = regno / REGSET_ELT_BITS;
- + bit = 1 << (regno % REGSET_ELT_BITS);
- + compl_bit = ~bit;
- + if (!found)
- + { /* regno was only loaded and never used - the load can be deleted */
- + delete_insn_for_stacker (last_set);
- + basic_block_maybe_live_at_end[source_blocknum][offset] &= compl_bit;
- + return (1);
- + }
- + /* Mark regno as dead at last_use */
- + note = gen_rtx (EXPR_LIST, REG_DEAD, regno_reg_rtx[regno],
- + REG_NOTES (last_use));
- + XEXP (note, 1) = REG_NOTES (last_use);
- + REG_NOTES (last_use) = note;
- + basic_block_maybe_live_at_end[source_blocknum][offset] &= compl_bit;
- + return (1);
- + }
- +
- +
- + /*
- + Starting at block# block_num visit all successor blocks recursively
- + stopping at a block where regno is not live at exit or regno
- + is set in block
- + */
- + static int
- + visit_till_dies (regno, block_num)
- + int regno, block_num;
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register int bit = 1 << (regno % REGSET_ELT_BITS);
- + int ret_val = 1;
- + int already_visited;
- + rtx reg_death = NULL;
- +
- + already_visited = blocks_visited[block_num];
- + blocks_visited[block_num] = 1;
- + if (num_visits > n_basic_blocks * 2)
- + { /* Failed to find where regno dies */
- + return (0);
- + }
- + if (already_visited)
- + {
- + num_visits++;
- + return (1);
- + }
- + num_visits++;
- + if ((basic_block_maybe_live_at_end[block_num][offset] & bit)
- + && !(reg_death = reg_dies_in_block (regno, block_num)))
- + {
- + if (jump_target_block[block_num] != -1)
- + {
- + ret_val = visit_till_dies (regno, jump_target_block[block_num]);
- + }
- + if (ret_val && fall_thru_block[block_num] != -1)
- + {
- + ret_val = visit_till_dies (regno, fall_thru_block[block_num]);
- + }
- + return (ret_val);
- + }
- + else
- + {
- + if (reg_death)
- + {
- + death_blocks[block_num] = NEXT_INSN (reg_death);
- + }
- + return (1);
- + }
- + }
- +
- +
- + /* Return the insn where regno dies in the block if it does,
- + otherwise return NULL
- + */
- + static rtx
- + reg_dies_in_block (regno, block_num)
- + int regno, block_num;
- + {
- + rtx insn;
- +
- + for (insn = basic_block_head[block_num];
- + insn && insn != NEXT_INSN (basic_block_end[block_num]);
- + insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN && find_regno_note (insn, REG_DEAD, regno))
- + {
- + return (insn);
- + }
- + }
- + return (NULL);
- + }
- +
- + my_dump_block_info ()
- + {
- + int i;
- + int max_regno = max_reg_num();
- + for (i = 0; i < n_basic_blocks; i++)
- + {
- + register rtx head, jump;
- + register int regno;
- + fprintf (stack_reg_dump_file, "\nBasic block %d: first insn %d, last %d.\n",
- + i,
- + INSN_UID (basic_block_head[i]),
- + INSN_UID (basic_block_end[i]));
- + /* The control flow graph's storage is freed
- + now when flow_analysis returns.
- + Don't try to print it if it is gone. */
- + fprintf (stack_reg_dump_file, "Succesor blocks: %d %d\n",
- + fall_thru_block[i], jump_target_block[i]);
- + fprintf (stack_reg_dump_file, "\nRegisters live at start:");
- + for (regno = 0; regno < max_regno; regno++)
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register int bit = 1 << (regno % REGSET_ELT_BITS);
- + if (basic_block_live_at_start[i][offset] & bit)
- + {
- + fprintf (stack_reg_dump_file, " %d", regno);
- + }
- + }
- + fprintf (stack_reg_dump_file, "\n");
- + fprintf (stack_reg_dump_file, "Registers live at end:");
- + for (regno = 0; regno < max_regno; regno++)
- + {
- + register int offset = regno / REGSET_ELT_BITS;
- + register int bit = 1 << (regno % REGSET_ELT_BITS);
- + if (basic_block_maybe_live_at_end[i][offset] & bit)
- + {
- + fprintf (stack_reg_dump_file, " %d", regno);
- + }
- + }
- + fprintf (stack_reg_dump_file, "\n");
- + }
- + fprintf (stack_reg_dump_file, "\n");
- + }
- +
- + #define MINUS0 0x80000000
- +
- + /*
- + change floating point compares to integer compares
- + */
- +
- + void
- + float_to_int_cmp (f, allow_new_jumps)
- + rtx f;
- + {
- + union
- + {
- + int i[2];
- + double d;
- + }
- + u1;
- + union
- + {
- + int i;
- + float f;
- + }
- + u2;
- + int block, found, next_is_ok, rev_new_targets, const_is_zero, no_new_jump,
- + change_org_jump, new_org_cond, rev_org_targets, new_jump_cond,
- + make_new_lab, new_lab_true;
- + rtx insn, sf_reg, sf_dead_note, last_set, mem_loaded, int_cmp, cmp_part,
- + op1, next, org_jump_insn, double_const, tmp, new_jump, new_jump_insn,
- + new_label, new_label_insn, gen_cmpsi_1 ();
- +
- + if (HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- + || HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
- + {
- + return;
- + }
- + if (TARGET_IEEE_FP)
- + {
- + return;
- + }
- + insn = f;
- + for (insn; insn != NULL; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == PARALLEL)
- + {
- + if (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
- + {
- + cmp_part = XVECEXP (PATTERN (insn), 0, 0);
- + if (SET_DEST (cmp_part) == cc0_rtx
- + && GET_CODE (SET_SRC (cmp_part)) == COMPARE
- + && (GET_MODE (SET_SRC (cmp_part)) == CCmode
- + || GET_MODE (SET_SRC (cmp_part)) == VOIDmode)
- + && (
- + (GET_CODE (XEXP (SET_SRC (cmp_part), 0)) == FLOAT_EXTEND
- + && GET_CODE (XEXP (XEXP (SET_SRC (cmp_part), 0), 0)) == REG
- + && REGNO (XEXP (XEXP (SET_SRC (cmp_part), 0), 0)) == FIRST_FLOAT_REG
- + && GET_MODE (XEXP (XEXP (SET_SRC (cmp_part), 0), 0)) == SFmode)
- + || /* Will have to make sure later it was loaded
- + from SFmode */
- + (GET_CODE (XEXP (SET_SRC (cmp_part), 0)) == REG
- + && REGNO (XEXP (SET_SRC (cmp_part), 0)) == FIRST_FLOAT_REG
- + && GET_MODE (XEXP (SET_SRC (cmp_part), 0)) == DFmode)
- + )
- + && GET_CODE (XEXP (SET_SRC (cmp_part), 1)) == MEM)
- + {
- + if (CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (SET_SRC (cmp_part), 1), 0)))
- + {
- + double_const
- + = get_pool_constant (XEXP (XEXP (SET_SRC (cmp_part), 1), 0));
- + if (GET_CODE (double_const) == CONST_DOUBLE)
- + {
- + u1.i[0] = CONST_DOUBLE_LOW (double_const);
- + u1.i[1] = CONST_DOUBLE_HIGH (double_const);
- + u2.f = u1.d;
- + if (GET_CODE (XEXP (SET_SRC (cmp_part), 0)) == FLOAT_EXTEND)
- + sf_reg = XEXP (XEXP (SET_SRC (cmp_part), 0), 0);
- + else
- + sf_reg = XEXP (SET_SRC (cmp_part), 0);
- + sf_dead_note
- + = find_regno_note (insn, REG_DEAD, REGNO (sf_reg));
- + }
- + else
- + {
- + double_const = NULL;
- + sf_dead_note = NULL;
- + }
- + }
- + else
- + {
- + double_const = NULL;
- + sf_dead_note = NULL;
- + }
- +
- + next_is_ok = 1;
- + no_new_jump = 0;
- + const_is_zero = 0;
- + if (u1.d == 0.0)
- + { /* 0.0 needs special handling because -0.0 has
- + a different representation */
- + const_is_zero = 1;
- + next_is_ok = 0;
- + rev_new_targets = 0;
- + change_org_jump = 0;
- + rev_org_targets = 0;
- + new_jump_cond = EQ;
- + make_new_lab = 0;
- + new_lab_true = 0;
- + next = NEXT_INSN (insn);
- + if (allow_new_jumps
- + && GET_CODE (next) == JUMP_INSN
- + && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
- + {
- + org_jump_insn = next;
- + if (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == LT
- + && XEXP (SET_SRC (PATTERN (next)), 1) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx)
- + {
- + next_is_ok = 1;
- + rev_new_targets = 1;
- + }
- + else if (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == GT
- + && XEXP (SET_SRC (PATTERN (next)), 1) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx)
- + {
- + next_is_ok = 1;
- + rev_new_targets = 1;
- + change_org_jump = 1;
- + new_org_cond = LE;
- + rev_org_targets = 1;
- + no_new_jump = 1;
- + }
- + else if (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == EQ
- + && XEXP (SET_SRC (PATTERN (next)), 1) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx)
- + {
- + next_is_ok = 1;
- + new_jump_cond = NE;
- + rev_new_targets = 1;
- + /* The original jump will jump to the new
- + label, that will be placed immediately
- + after the new jump. */
- + make_new_lab = 1;
- + /* The new label is to be jumped to
- + if the condition is true */
- + new_lab_true = 1;
- + }
- + else if (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == NE
- + && XEXP (SET_SRC (PATTERN (next)), 1) != pc_rtx
- + && XEXP (SET_SRC (PATTERN (next)), 2) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx)
- + {
- + next_is_ok = 1;
- + change_org_jump = 1;
- + new_org_cond = EQ;
- + new_jump_cond = NE;
- + /* The original jump will jump to the new
- + label, that will be placed immediately
- + after the new jump. */
- + make_new_lab = 1;
- + /* The new label is to be jumped to
- + if the condition is true */
- + new_lab_true = 1;
- + }
- + else if ((GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == GE
- + && XEXP (SET_SRC (PATTERN (next)), 1) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx)
- + ||
- + (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == LT
- + && XEXP (SET_SRC (PATTERN (next)), 1) != pc_rtx
- + && XEXP (SET_SRC (PATTERN (next)), 2) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx))
- + {
- + next_is_ok = 1;
- + change_org_jump = 1;
- + new_org_cond = GE;
- + new_jump_cond = NE;
- + rev_new_targets = 1;
- + /* The original jump will jump to the new
- + label, that will be placed immediately
- + after the new jump. */
- + make_new_lab = 1;
- + /* The new label is to be jumped to
- + if the condition is true */
- + new_lab_true = 1;
- + }
- + else if (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == GT
- + && XEXP (SET_SRC (PATTERN (next)), 1) != pc_rtx
- + && XEXP (SET_SRC (PATTERN (next)), 2) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx)
- + {
- + next_is_ok = 1;
- + no_new_jump = 1;
- + }
- + else if ((GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == GE
- + || GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == EQ)
- + && XEXP (SET_SRC (PATTERN (next)), 1) != pc_rtx
- + && XEXP (SET_SRC (PATTERN (next)), 2) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx)
- + {
- + next_is_ok = 1;
- + }
- + else if (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == NE
- + && XEXP (SET_SRC (PATTERN (next)), 1) == pc_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 0) == cc0_rtx
- + && XEXP (XEXP (SET_SRC (PATTERN (next)), 0), 1) == const0_rtx)
- + {
- + next_is_ok = 1;
- + }
- + else if (GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)) == LE)
- + {
- + next_is_ok = 1;
- + no_new_jump = 1;
- + }
- + }
- + }
- + if (sf_dead_note
- + && next_is_ok
- + && u1.d >= 0.0
- + && ((double) u2.f == u1.d)
- + && ((float) u1.d == u2.f))
- + { /* Find where the sf_reg was loaded from. */
- + last_set = PREV_INSN (insn);
- + found = 0;
- + while (!found && last_set)
- + {
- + if (GET_CODE (last_set) == INSN)
- + {
- + if (GET_CODE (PATTERN (last_set)) == SET
- + && rtx_equal_p (sf_reg,
- + SET_DEST (PATTERN (last_set)))
- + &&
- + (GET_CODE (SET_SRC (PATTERN (last_set)))
- + == MEM ||
- + (GET_CODE (SET_SRC (PATTERN (last_set)))
- + == FLOAT_EXTEND
- + &&
- + GET_CODE (XEXP (SET_SRC (PATTERN (last_set)),0))
- + == MEM)
- + ))
- + {
- + if (GET_CODE (SET_SRC (PATTERN (last_set)))
- + == FLOAT_EXTEND)
- + {
- + mem_loaded =
- + XEXP (SET_SRC (PATTERN (last_set)),0);
- + found = 1;
- + }
- + else if (GET_CODE (XEXP (SET_SRC (cmp_part), 0))
- + == FLOAT_EXTEND)
- + {
- + mem_loaded =
- + SET_SRC (PATTERN (last_set));
- + found = 1;
- + }
- + else
- + {
- + last_set = NULL;
- + }
- + }
- + else if (GET_CODE (PATTERN (last_set)) == SET
- + && GET_CODE (SET_DEST (PATTERN (last_set)))
- + == REG
- + && !IS_STACK_MODE (
- + GET_MODE (SET_DEST (PATTERN (last_set)))))
- + {
- + last_set = PREV_INSN (last_set);
- + }
- + else
- + last_set = NULL;
- + }
- + else if (GET_CODE (last_set) == NOTE)
- + {
- + last_set = PREV_INSN (last_set);
- + }
- + else
- + last_set = NULL;
- + }
- + if (last_set)
- + {
- + op1 = gen_rtx (MEM, SImode, XEXP (mem_loaded,0));
- + /* See if op1 is also in a register. */
- + if (next_nonnote_insn (last_set) == insn)
- + {
- + tmp = prev_nonnote_insn (last_set);
- + }
- + else
- + {
- + tmp = next_nonnote_insn (last_set);
- + if (next_nonnote_insn (tmp) != insn)
- + {
- + tmp = NULL;
- + }
- + }
- + if (tmp
- + && GET_CODE (tmp) == INSN
- + && GET_CODE (PATTERN (tmp)) == SET
- + && GET_CODE (SET_DEST (PATTERN (tmp))) == REG
- + && rtx_equal_p (op1,
- + SET_SRC (PATTERN (tmp))))
- + {
- + op1 = SET_DEST (PATTERN (tmp));
- + }
- + int_cmp
- + = gen_cmpsi_1 (op1,
- + gen_rtx (CONST_INT, 0, u2.i));
- + PATTERN (insn) = int_cmp;
- + INSN_CODE (insn) = recog (int_cmp, insn);
- + remove_note (insn, sf_dead_note);
- + reg_n_deaths[REGNO (sf_reg)]--;
- + PUT_CODE (last_set, NOTE);
- + NOTE_LINE_NUMBER (last_set) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (last_set) = 0;
- + if (const_is_zero && change_org_jump)
- + {
- + PUT_CODE (XEXP (SET_SRC (PATTERN (org_jump_insn)), 0),
- + new_org_cond);
- + INSN_CODE (org_jump_insn)
- + = recog (PATTERN (org_jump_insn), org_jump_insn);
- + }
- + if (const_is_zero && rev_org_targets)
- + {
- +
- + tmp = XEXP (SET_SRC (PATTERN (org_jump_insn)), 1);
- + XEXP (SET_SRC (PATTERN (org_jump_insn)), 1)
- + = XEXP (SET_SRC (PATTERN (org_jump_insn)), 2);
- + XEXP (SET_SRC (PATTERN (org_jump_insn)), 2) = tmp;
- + INSN_CODE (org_jump_insn)
- + = recog (PATTERN (org_jump_insn), org_jump_insn);
- + }
- + if (const_is_zero && !no_new_jump)
- + {
- + new_jump = copy_rtx (PATTERN (next));
- + PUT_CODE (XEXP (SET_SRC (new_jump), 0), new_jump_cond);
- + if (rev_new_targets)
- + {
- + tmp = XEXP (SET_SRC (new_jump), 1);
- + XEXP (SET_SRC (new_jump), 1)
- + = XEXP (SET_SRC (new_jump), 2);
- + XEXP (SET_SRC (new_jump), 2) = tmp;
- + }
- + int_cmp
- + = gen_cmpsi_1 (op1,
- + gen_rtx (CONST_INT, 0, MINUS0));
- + int_cmp
- + = emit_insn_before (int_cmp, NEXT_INSN (next));
- + INSN_CODE (int_cmp) = INSN_CODE (insn);
- + new_jump_insn
- + = emit_jump_insn_after (new_jump, int_cmp);
- + INSN_CODE (new_jump_insn)
- + = recog (new_jump, new_jump_insn);
- + }
- + if (const_is_zero && make_new_lab)
- + {
- + if (no_new_jump)
- + abort ();
- + new_label = gen_label_rtx ();
- + new_label_insn
- + = emit_label_after (new_label, new_jump_insn);
- + ++LABEL_NUSES (new_label_insn);
- + JUMP_LABEL (org_jump_insn) = new_label_insn;
- + if (new_lab_true)
- + {
- + XEXP (SET_SRC (PATTERN (org_jump_insn)), 1)
- + = gen_rtx (LABEL_REF, VOIDmode, new_label);
- + XEXP (SET_SRC (PATTERN (org_jump_insn)), 2)
- + = pc_rtx;
- + }
- + else
- + {
- + XEXP (SET_SRC (PATTERN (org_jump_insn)), 1)
- + = pc_rtx;
- + XEXP (SET_SRC (PATTERN (org_jump_insn)), 2)
- + = gen_rtx (LABEL_REF, VOIDmode, new_label);
- + }
- + INSN_CODE (org_jump_insn)
- + = recog (PATTERN (org_jump_insn), org_jump_insn);
- + }
- + }
- + }
- + }
- + }
- + }
- + }
- + }
- +
- + #endif
- #endif /* STACK_REGS */
- diff -rNci gcc-2.7.2/reload.c gcc-2.7.2p/reload.c
- *** gcc-2.7.2/reload.c Sat Nov 11 13:23:54 1995
- --- gcc-2.7.2p/reload.c Tue Jan 23 09:25:30 1996
- ***************
- *** 98,104 ****
- #include "hard-reg-set.h"
- #include "flags.h"
- #include "real.h"
- - #include "output.h"
-
- #ifndef REGISTER_MOVE_COST
- #define REGISTER_MOVE_COST(x, y) 2
- --- 98,103 ----
- ***************
- *** 357,372 ****
-
- *picode = CODE_FOR_nothing;
-
- - /* If X is a paradoxical SUBREG, use the inner value to determine both the
- - mode and object being reloaded. */
- - if (GET_CODE (x) == SUBREG
- - && (GET_MODE_SIZE (GET_MODE (x))
- - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
- - {
- - x = SUBREG_REG (x);
- - reload_mode = GET_MODE (x);
- - }
- -
- /* If X is a pseudo-register that has an equivalent MEM (actually, if it
- is still a pseudo-register by now, it *must* have an equivalent MEM
- but we don't want to assume that), use that equivalent when seeing if
- --- 356,361 ----
- ***************
- *** 735,741 ****
- {
- register int i;
- int dont_share = 0;
- - int dont_remove_subreg = 0;
- rtx *in_subreg_loc = 0, *out_subreg_loc = 0;
- int secondary_in_reload = -1, secondary_out_reload = -1;
- enum insn_code secondary_in_icode = CODE_FOR_nothing;
- --- 724,729 ----
- ***************
- *** 902,915 ****
- != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
- GET_MODE (SUBREG_REG (in)))))))
- {
- - /* This relies on the fact that emit_reload_insns outputs the
- - instructions for input reloads of type RELOAD_OTHER in the same
- - order as the reloads. Thus if the outer reload is also of type
- - RELOAD_OTHER, we are guaranteed that this inner reload will be
- - output before the outer reload. */
- push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
- GENERAL_REGS, VOIDmode, VOIDmode, 0, 0, opnum, type);
- - dont_remove_subreg = 1;
- }
-
-
- --- 890,897 ----
- ***************
- *** 971,1006 ****
- outmode = GET_MODE (out);
- }
-
- - /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- - either M1 is not valid for R or M2 is wider than a word but we only
- - need one word to store an M2-sized quantity in R.
- -
- - However, we must reload the inner reg *as well as* the subreg in
- - that case. In this case, the inner reg is an in-out reload. */
- -
- - if (out != 0 && GET_CODE (out) == SUBREG
- - && GET_CODE (SUBREG_REG (out)) == REG
- - && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
- - && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (out)), outmode)
- - || (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
- - && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
- - > UNITS_PER_WORD)
- - && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
- - / UNITS_PER_WORD)
- - != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
- - GET_MODE (SUBREG_REG (out)))))))
- - {
- - /* This relies on the fact that emit_reload_insns outputs the
- - instructions for output reloads of type RELOAD_OTHER in reverse
- - order of the reloads. Thus if the outer reload is also of type
- - RELOAD_OTHER, we are guaranteed that this inner reload will be
- - output after the outer reload. */
- - dont_remove_subreg = 1;
- - push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
- - &SUBREG_REG (out), ALL_REGS, VOIDmode, VOIDmode, 0, 0,
- - opnum, RELOAD_OTHER);
- - }
- -
- /* If IN appears in OUT, we can't share any input-only reload for IN. */
- if (in != 0 && out != 0 && GET_CODE (out) == MEM
- && (GET_CODE (in) == REG || GET_CODE (in) == MEM)
- --- 953,958 ----
- ***************
- *** 1011,1026 ****
- simplifies some of the cases below. */
-
- if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
- ! && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
- ! && ! dont_remove_subreg)
- in = gen_rtx (REG, GET_MODE (in),
- REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
-
- /* Similarly for OUT. */
- if (out != 0 && GET_CODE (out) == SUBREG
- && GET_CODE (SUBREG_REG (out)) == REG
- ! && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
- ! && ! dont_remove_subreg)
- out = gen_rtx (REG, GET_MODE (out),
- REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
-
- --- 963,976 ----
- simplifies some of the cases below. */
-
- if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
- ! && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
- in = gen_rtx (REG, GET_MODE (in),
- REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
-
- /* Similarly for OUT. */
- if (out != 0 && GET_CODE (out) == SUBREG
- && GET_CODE (SUBREG_REG (out)) == REG
- ! && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
- out = gen_rtx (REG, GET_MODE (out),
- REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
-
- ***************
- *** 4120,4125 ****
- --- 4070,4079 ----
- {
- register int regno;
- rtx tem;
- + #ifdef REWRITE_ADDRESS
- + /* intel1 */
- + rtx rewrite_address();
- + #endif
-
- /* If the address is a register, see if it is a legitimate address and
- reload if not. We first handle the cases where we need not reload
- ***************
- *** 4247,4261 ****
- return 0;
- }
-
- ! /* If we have address of a stack slot but it's not valid because the
- ! displacement is too large, compute the sum in a register.
- ! Handle all base registers here, not just fp/ap/sp, because on some
- ! targets (namely SH) we can also get too large displacements from
- ! big-endian corrections. */
- else if (GET_CODE (ad) == PLUS
- ! && GET_CODE (XEXP (ad, 0)) == REG
- ! && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
- ! && REG_OK_FOR_BASE_P (XEXP (ad, 0))
- && GET_CODE (XEXP (ad, 1)) == CONST_INT)
- {
- /* Unshare the MEM rtx so we can safely alter it. */
- --- 4201,4217 ----
- return 0;
- }
-
- ! /* If we have address of a stack slot but it's not valid
- ! (displacement is too large), compute the sum in a register. */
- else if (GET_CODE (ad) == PLUS
- ! && (XEXP (ad, 0) == frame_pointer_rtx
- ! #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- ! || XEXP (ad, 0) == hard_frame_pointer_rtx
- ! #endif
- ! #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- ! || XEXP (ad, 0) == arg_pointer_rtx
- ! #endif
- ! || XEXP (ad, 0) == stack_pointer_rtx)
- && GET_CODE (XEXP (ad, 1)) == CONST_INT)
- {
- /* Unshare the MEM rtx so we can safely alter it. */
- ***************
- *** 4383,4388 ****
- --- 4339,4375 ----
- }
- }
-
- + /* intel1 - even if one of the registers is still a pseudo
- + subst_reg_equivs may be able to substitute a
- + constant for it too */
- + else
- +
- + if (tem != ad && memory_address_p (mode, tem))
- + {
- + rtx tmp_rtx;
- + tmp_rtx = copy_rtx (tem);
- + /* Ok, we win that way. Replace any additional eliminable
- + registers. */
- + subst_reg_equivs_changed = 0;
- + tmp_rtx = subst_reg_equivs (tmp_rtx);
- + #ifdef REWRITE_ADDRESS
- + if (!strict_memory_address_p (mode, tmp_rtx))
- + {
- + tmp_rtx = gen_rtx (MEM, mode, tmp_rtx);
- + REWRITE_ADDRESS (tmp_rtx);
- + tmp_rtx = XEXP (tmp_rtx, 0);
- + }
- + #endif
- +
- + /* Make sure that didn't make the address invalid again. */
- +
- + if (strict_memory_address_p (mode, tmp_rtx))
- + {
- + *loc = tmp_rtx;
- + return 0;
- + }
- +
- + }
- /* If constants aren't valid addresses, reload the constant address
- into a register. */
- if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad))
- ***************
- *** 4609,4626 ****
- {
- op0 = SUBREG_REG (op0);
- code0 = GET_CODE (op0);
- - if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER)
- - op0 = gen_rtx (REG, word_mode,
- - REGNO (op0) + SUBREG_WORD (orig_op0));
- }
-
- if (GET_CODE (op1) == SUBREG)
- {
- op1 = SUBREG_REG (op1);
- code1 = GET_CODE (op1);
- - if (code1 == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER)
- - op1 = gen_rtx (REG, GET_MODE (op1),
- - REGNO (op1) + SUBREG_WORD (orig_op1));
- }
-
- if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
- --- 4596,4607 ----
- ***************
- *** 4882,4918 ****
- return 0;
-
- case SUBREG:
- ! if (GET_CODE (SUBREG_REG (x)) == REG)
- {
- ! /* If this is a SUBREG of a hard register and the resulting register
- ! is of the wrong class, reload the whole SUBREG. This avoids
- ! needless copies if SUBREG_REG is multi-word. */
- ! if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
- ! {
- ! int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
-
- ! if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
- ! : REGNO_OK_FOR_BASE_P (regno)))
- ! {
- ! push_reload (x, NULL_RTX, loc, NULL_PTR,
- ! context ? INDEX_REG_CLASS : BASE_REG_CLASS,
- ! GET_MODE (x), VOIDmode, 0, 0, opnum, type);
- ! return 1;
- ! }
- ! }
- ! /* If this is a SUBREG of a pseudo-register, and the pseudo-register
- ! is larger than the class size, then reload the whole SUBREG. */
- ! else
- {
- ! enum reg_class class = (context
- ! ? INDEX_REG_CLASS : BASE_REG_CLASS);
- ! if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
- ! > reg_class_size[class])
- ! {
- ! push_reload (x, NULL_RTX, loc, NULL_PTR, class,
- ! GET_MODE (x), VOIDmode, 0, 0, opnum, type);
- ! return 1;
- ! }
- }
- }
- break;
- --- 4863,4883 ----
- return 0;
-
- case SUBREG:
- ! /* If this is a SUBREG of a hard register and the resulting register is
- ! of the wrong class, reload the whole SUBREG. This avoids needless
- ! copies if SUBREG_REG is multi-word. */
- ! if (GET_CODE (SUBREG_REG (x)) == REG
- ! && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
- {
- ! int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
-
- ! if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
- ! : REGNO_OK_FOR_BASE_P (regno)))
- {
- ! push_reload (x, NULL_RTX, loc, NULL_PTR,
- ! context ? INDEX_REG_CLASS : BASE_REG_CLASS,
- ! GET_MODE (x), VOIDmode, 0, 0, opnum, type);
- ! return 1;
- }
- }
- break;
- ***************
- *** 5193,5199 ****
- && refers_to_regno_for_reload_p (regno, endregno,
- SUBREG_REG (SET_DEST (x)),
- loc))
- ! /* If the output is an earlyclobber operand, this is
- a conflict. */
- || ((GET_CODE (SET_DEST (x)) != REG
- || earlyclobber_operand_p (SET_DEST (x)))
- --- 5158,5164 ----
- && refers_to_regno_for_reload_p (regno, endregno,
- SUBREG_REG (SET_DEST (x)),
- loc))
- ! /* If the ouput is an earlyclobber operand, this is
- a conflict. */
- || ((GET_CODE (SET_DEST (x)) != REG
- || earlyclobber_operand_p (SET_DEST (x)))
- ***************
- *** 5597,5608 ****
- goal_mem
- || need_stable_sp))
- return 0;
- -
- - #ifdef NON_SAVING_SETJMP
- - if (NON_SAVING_SETJMP && GET_CODE (p) == NOTE
- - && NOTE_LINE_NUMBER (p) == NOTE_INSN_SETJMP)
- - return 0;
- - #endif
-
- #ifdef INSN_CLOBBERS_REGNO_P
- if ((valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER
- --- 5562,5567 ----
- diff -rNci gcc-2.7.2/reload.h gcc-2.7.2p/reload.h
- *** gcc-2.7.2/reload.h Thu Jun 15 12:00:35 1995
- --- gcc-2.7.2p/reload.h Tue Jan 23 09:25:30 1996
- ***************
- *** 235,237 ****
- --- 235,249 ----
-
- /* Find the places where hard regs are live across calls and save them. */
- extern void save_call_clobbered_regs PROTO((enum machine_mode));
- + /* intel1 */
- + #define MAX_RELOAD_STACK_SLOTS 100
- + struct reload_slot_info {
- + rtx reload_stack_slot;
- + rtx reload_insn;
- + rtx last_store;
- + int is_loaded_to_reg;
- + int stack_slot_pseudo_reg;
- + int cur_stack_offset;
- + char reload_stack_mode;
- + unsigned reload_slot_updated:1;
- + } ;
- diff -rNci gcc-2.7.2/reload1.c gcc-2.7.2p/reload1.c
- *** gcc-2.7.2/reload1.c Sun Nov 5 16:22:22 1995
- --- gcc-2.7.2p/reload1.c Tue Jan 23 09:25:31 1996
- ***************
- *** 34,40 ****
- #include "recog.h"
- #include "basic-block.h"
- #include "output.h"
- - #include "real.h"
-
- /* This file contains the reload pass of the compiler, which is
- run after register allocation has been done. It checks that
- --- 34,39 ----
- ***************
- *** 77,82 ****
- --- 76,83 ----
- #ifndef MEMORY_MOVE_COST
- #define MEMORY_MOVE_COST(x) 4
- #endif
- + /* intel1 */
- + static int cur_stack_offset;
-
- /* During reload_as_needed, element N contains a REG rtx for the hard reg
- into which reg N has been reloaded (perhaps for a previous insn). */
- ***************
- *** 268,273 ****
- --- 269,277 ----
- #define obstack_chunk_alloc xmalloc
- #define obstack_chunk_free free
-
- + /* intel1 */
- + extern FILE * global_reg_dump_file;
- +
- /* List of labels that must never be deleted. */
- extern rtx forced_labels;
-
- ***************
- *** 308,313 ****
- --- 312,326 ----
-
- #define NUM_ELIMINABLE_REGS (sizeof reg_eliminate / sizeof reg_eliminate[0])
-
- + /* intel1 */
- + /* information for loop_after_global optimizations */
- + struct reload_slot_info reload_slots[MAX_RELOAD_STACK_SLOTS];
- + int num_reload_stack_slots=0;
- + static rtx treplace_insn = NULL_RTX;
- +
- + /* is 1 is the pseudo has been spilled */
- + int * pseudo_spilled;
- +
- /* Record the number of pending eliminations that have an offset not equal
- to their initial offset. If non-zero, we use a new copy of each
- replacement result in any insns encountered. */
- ***************
- *** 372,377 ****
- --- 385,392 ----
- static void inc_for_reload PROTO((rtx, rtx, int));
- static int constraint_accepts_reg_p PROTO((char *, rtx));
- static int count_occurrences PROTO((rtx, rtx));
- + /* intel1 */
- + int is_a_param_slot();
-
- /* Initialize the reload pass once per compilation. */
-
- ***************
- *** 466,471 ****
- --- 481,506 ----
- /* The basic block number currently being processed for INSN. */
- int this_block;
-
- + /* intel1 */
- + /* intel1. Look for insns whose src is equal to dest and delete them. */
- + for (insn = next_nonnote_insn (first); insn; insn = next_nonnote_insn (insn))
- + {
- + if (GET_CODE (insn) == INSN
- + && GET_CODE (PATTERN (insn)) == SET
- + && !(GET_CODE (SET_SRC (PATTERN (insn))) == MEM
- + && MEM_VOLATILE_P (SET_SRC (PATTERN (insn))))
- + && rtx_equal_p (SET_SRC (PATTERN (insn)), SET_DEST (PATTERN (insn))))
- + {
- + PUT_CODE (insn, NOTE);
- + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- + NOTE_SOURCE_FILE (insn) = 0;
- + }
- + }
- + num_reload_stack_slots = 0;
- + pseudo_spilled = (int *)alloca(max_regno*sizeof(int));
- + bzero(pseudo_spilled,max_regno*sizeof(int));
- + bzero(reload_slots,MAX_RELOADS*sizeof(struct reload_slot_info));
- +
- /* Make sure even insns with volatile mem refs are recognizable. */
- init_recog ();
-
- ***************
- *** 814,819 ****
- --- 849,857 ----
-
- num_not_at_initial_offset = 0;
-
- + /* intel1 */
- + cur_stack_offset = 0;
- +
- bzero ((char *) &offsets_known_at[get_first_label_num ()], num_labels);
-
- /* Set a known offset for each forced label to be at the initial offset
- ***************
- *** 1955,1960 ****
- --- 1993,2034 ----
-
- reload_in_progress = 0;
-
- + /* intel1 */
- + for (insn = first; insn; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
- + && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- + && GET_CODE (SET_SRC (PATTERN (insn))) == REG)
- + {
- + if (REGNO (SET_DEST (PATTERN (insn))) < FIRST_PSEUDO_REGISTER
- + && REGNO (SET_SRC (PATTERN (insn))) >= FIRST_PSEUDO_REGISTER
- + && reg_equiv_mem[REGNO (SET_SRC (PATTERN (insn)))]
- + && reg_renumber[REGNO (SET_SRC (PATTERN (insn)))] < 0
- + && RTX_IS_SPILL_P (reg_equiv_mem[REGNO (SET_SRC (PATTERN (insn)))])
- + && !RTX_IS_SPILL_P (insn))
- + {
- + RTX_IS_SPILL_P (insn) = 1;
- + SPILL_PSEUDO (insn) = REGNO (SET_SRC (PATTERN (insn)));
- + }
- + if (REGNO (SET_DEST (PATTERN (insn))) >= FIRST_PSEUDO_REGISTER
- + && REGNO (SET_SRC (PATTERN (insn))) < FIRST_PSEUDO_REGISTER
- + && reg_equiv_mem[REGNO (SET_DEST (PATTERN (insn)))]
- + && reg_renumber[REGNO (SET_DEST (PATTERN (insn)))] < 0
- + && RTX_IS_SPILL_P (reg_equiv_mem[REGNO (SET_DEST (PATTERN (insn)))])
- + && !RTX_IS_SPILL_P (insn))
- + {
- + RTX_IS_SPILL_P (insn) = 1;
- + SPILL_PSEUDO (insn) = REGNO (SET_DEST (PATTERN (insn)));
- + }
- + if (scratch_list)
- + free (scratch_list);
- + scratch_list = 0;
- + if (scratch_block)
- + free (scratch_block);
- + scratch_block = 0;
- +
- + }
- + }
- /* Now eliminate all pseudo regs by modifying them into
- their equivalent memory references.
- The REG-rtx's for the pseudos are modified in place,
- ***************
- *** 2016,2028 ****
- reg_equiv_constant = 0;
- reg_equiv_memory_loc = 0;
-
- ! if (scratch_list)
- ! free (scratch_list);
- ! scratch_list = 0;
- ! if (scratch_block)
- ! free (scratch_block);
- ! scratch_block = 0;
- !
- return failure;
- }
-
- --- 2090,2106 ----
- reg_equiv_constant = 0;
- reg_equiv_memory_loc = 0;
-
- ! /* intel1 */
- ! if (num_reload_stack_slots == MAX_RELOAD_STACK_SLOTS)
- ! { /* Too many so don't use any */
- ! for (insn = first; insn ; insn = next_nonnote_insn (insn))
- ! {
- ! if (GET_CODE (insn) == INSN )
- ! {
- ! RTX_IS_SPILL_P (insn) = 0;
- ! }
- ! }
- ! }
- return failure;
- }
-
- ***************
- *** 2325,2330 ****
- --- 2403,2417 ----
- REGNO (regno_reg_rtx[i])
- = reg_renumber[i] >= 0 ? reg_renumber[i] : i;
-
- + /* intel1 */
- + if (reg_renumber[i] < 0
- + && reg_equiv_memory_loc[i] != 0
- + && is_a_param_slot (reg_equiv_memory_loc[i]))
- + {
- + pseudo_spilled[i] = 1;
- + RTX_IS_SPILL_P (reg_equiv_memory_loc[i]) = 1;
- + RTX_IS_SPILL_P (XEXP (reg_equiv_memory_loc[i], 0)) = 1;
- + }
- /* If we have a pseudo that is needed but has no hard reg or equivalent,
- allocate a stack slot for it. */
-
- ***************
- *** 2338,2343 ****
- --- 2425,2432 ----
- int total_size = MAX (inherent_size, reg_max_ref_width[i]);
- int adjust = 0;
-
- + /* intel1 */
- + pseudo_spilled[i] = 1;
- /* Each pseudo reg has an inherent size which comes from its own mode,
- and a total size which provides room for paradoxical subregs
- which refer to the pseudo reg in wider modes.
- ***************
- *** 2350,2362 ****
- {
- /* No known place to spill from => no slot to reuse. */
- x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size, -1);
- if (BYTES_BIG_ENDIAN)
- /* Cancel the big-endian correction done in assign_stack_local.
- Get the address of the beginning of the slot.
- This is so we can do a big-endian correction unconditionally
- below. */
- adjust = inherent_size - total_size;
- -
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
- }
- /* Reuse a stack slot if possible. */
- --- 2439,2453 ----
- {
- /* No known place to spill from => no slot to reuse. */
- x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size, -1);
- + /* intel1 */
- + RTX_IS_SPILL_P (x) = 1;
- + RTX_IS_SPILL_P (XEXP (x, 0)) = 1;
- if (BYTES_BIG_ENDIAN)
- /* Cancel the big-endian correction done in assign_stack_local.
- Get the address of the beginning of the slot.
- This is so we can do a big-endian correction unconditionally
- below. */
- adjust = inherent_size - total_size;
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
- }
- /* Reuse a stack slot if possible. */
- ***************
- *** 2364,2370 ****
- --- 2455,2463 ----
- && spill_stack_slot_width[from_reg] >= total_size
- && (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))
- >= inherent_size))
- + {
- x = spill_stack_slot[from_reg];
- + }
- /* Allocate a bigger slot. */
- else
- {
- ***************
- *** 2383,2400 ****
- /* Make a slot with that size. */
- x = assign_stack_local (mode, total_size, -1);
- stack_slot = x;
- if (BYTES_BIG_ENDIAN)
- {
- /* Cancel the big-endian correction done in assign_stack_local.
- ! Get the address of the beginning of the slot.
- ! This is so we can do a big-endian correction unconditionally
- ! below. */
- adjust = GET_MODE_SIZE (mode) - total_size;
- ! if (adjust)
- ! stack_slot = gen_rtx (MEM, mode_for_size (total_size
- ! * BITS_PER_UNIT,
- ! MODE_INT, 1),
- ! plus_constant (XEXP (x, 0), adjust));
- }
- spill_stack_slot[from_reg] = stack_slot;
- spill_stack_slot_width[from_reg] = total_size;
- --- 2476,2496 ----
- /* Make a slot with that size. */
- x = assign_stack_local (mode, total_size, -1);
- stack_slot = x;
- + /* intel1 */
- + RTX_IS_SPILL_P (x) = 1;
- + RTX_IS_SPILL_P (XEXP (x, 0)) = 1;
- if (BYTES_BIG_ENDIAN)
- {
- /* Cancel the big-endian correction done in assign_stack_local.
- ! Get the address of the beginning of the slot.
- ! This is so we can do a big-endian correction unconditionally
- ! below. */
- adjust = GET_MODE_SIZE (mode) - total_size;
- ! if(adjust)
- ! stack_slot = gen_rtx (MEM, mode_for_size (total_size
- ! * BITS_PER_UNIT,
- ! MODE_INT, 1),
- ! plus_constant (XEXP (x, 0), adjust));
- }
- spill_stack_slot[from_reg] = stack_slot;
- spill_stack_slot_width[from_reg] = total_size;
- ***************
- *** 2412,2417 ****
- --- 2508,2516 ----
- x = gen_rtx (MEM, GET_MODE (regno_reg_rtx[i]),
- plus_constant (XEXP (x, 0), adjust));
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
- + /* intel1 */
- + RTX_IS_SPILL_P (x) = 1;
- + RTX_IS_SPILL_P (XEXP (x, 0)) = 1;
- }
-
- /* Save the stack slot for later. */
- ***************
- *** 2650,2655 ****
- --- 2749,2756 ----
- int i, j;
- char *fmt;
- int copied = 0;
- + /* intel1 */
- + int indx;
-
- switch (code)
- {
- ***************
- *** 2699,2704 ****
- --- 2800,2823 ----
- address in case it is shared. */
- new = eliminate_regs (reg_equiv_memory_loc[regno],
- mem_mode, insn);
- + /* intel1 */
- + if ((flag_loop_after_global || flag_peep_spills)
- + && treplace_insn && is_a_stack_slot (new)
- + && !is_a_reload_stack_slot (new, &indx, cur_stack_offset, treplace_insn)
- + && num_reload_stack_slots < MAX_RELOAD_STACK_SLOTS)
- + {
- + if (num_reload_stack_slots < MAX_RELOAD_STACK_SLOTS)
- + {
- + reload_slots[num_reload_stack_slots].cur_stack_offset
- + = cur_stack_offset;
- + reload_slots[num_reload_stack_slots].stack_slot_pseudo_reg
- + = regno;
- + reload_slots[num_reload_stack_slots].reload_stack_slot
- + = new;
- + reload_slots[num_reload_stack_slots++].reload_insn
- + = treplace_insn;
- + }
- + }
- if (new != reg_equiv_memory_loc[regno])
- {
- cannot_omit_stores[regno] = 1;
- ***************
- *** 3094,3103 ****
- --- 3213,3226 ----
- new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn);
- if (new != XEXP (x, 0))
- {
- + /* intel1 */
- + new->is_spill_rtx = x->is_spill_rtx;
- new = gen_rtx (MEM, GET_MODE (x), new);
- new->volatil = x->volatil;
- new->unchanging = x->unchanging;
- new->in_struct = x->in_struct;
- + /* intel1 */
- + new->is_spill_rtx = x->is_spill_rtx;
- return new;
- }
- else
- ***************
- *** 3236,3242 ****
- will delete it in reload_as_needed once we know that this
- elimination is, in fact, being done.
-
- ! If REPLACE isn't set, we can't delete this insn, but needn't
- process it since it won't be used unless something changes. */
- if (replace)
- delete_dead_insn (insn);
- --- 3359,3365 ----
- will delete it in reload_as_needed once we know that this
- elimination is, in fact, being done.
-
- ! If REPLACE isn't set, we can't delete this insn, but neededn't
- process it since it won't be used unless something changes. */
- if (replace)
- delete_dead_insn (insn);
- ***************
- *** 3288,3295 ****
- --- 3411,3422 ----
- re-recognize the insn. We do this in case we had a simple addition
- but now can do this as a load-address. This saves an insn in this
- common case. */
- + /* intel1 */
- + treplace_insn = replace ? insn : NULL_RTX;
-
- new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX);
- + /* intel1 */
- + treplace_insn = NULL_RTX;
- if (new_body != old_body)
- {
- /* If we aren't replacing things permanently and we changed something,
- ***************
- *** 3806,3812 ****
- {
- rtx avoid_return_reg = 0;
- rtx oldpat = PATTERN (insn);
- -
- #ifdef SMALL_REGISTER_CLASSES
- /* Set avoid_return_reg if this is an insn
- that might use the value of a function call. */
- --- 3933,3938 ----
- ***************
- *** 3961,3966 ****
- --- 4087,4102 ----
- forget_old_reloads_1 (XEXP (x, 0), NULL_RTX);
- }
- #endif
- + /* intel1 */
- + if (GET_CODE (PATTERN (insn)) == PARALLEL)
- + {
- + int i;
- + for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- + update_stack_offset (XVECEXP (PATTERN (insn), 0, i),
- + &cur_stack_offset);
- + }
- + else
- + update_stack_offset (PATTERN (insn), &cur_stack_offset);
- }
- /* A reload reg's contents are unknown after a label. */
- if (GET_CODE (insn) == CODE_LABEL)
- ***************
- *** 5650,5661 ****
- rtx output_address_reload_insns[MAX_RECOG_OPERANDS];
- rtx operand_reload_insns = 0;
- rtx other_operand_reload_insns = 0;
- - rtx other_output_reload_insns = 0;
- rtx following_insn = NEXT_INSN (insn);
- rtx before_insn = insn;
- int special;
- /* Values to be put in spill_reg_store are put here first. */
- rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
-
- for (j = 0; j < reload_n_operands; j++)
- input_reload_insns[j] = input_address_reload_insns[j]
- --- 5786,5798 ----
- rtx output_address_reload_insns[MAX_RECOG_OPERANDS];
- rtx operand_reload_insns = 0;
- rtx other_operand_reload_insns = 0;
- rtx following_insn = NEXT_INSN (insn);
- rtx before_insn = insn;
- int special;
- /* Values to be put in spill_reg_store are put here first. */
- rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
- + int indx; /* intel1 */
- + rtx tmp_stack_slot, reload_insn; /* intel1 */
-
- for (j = 0; j < reload_n_operands; j++)
- input_reload_insns[j] = input_address_reload_insns[j]
- ***************
- *** 6054,6062 ****
- third_reload_reg)));
- }
- else
- gen_reload (second_reload_reg, oldequiv,
- reload_opnum[j],
- ! reload_when_needed[j]);
-
- oldequiv = second_reload_reg;
- }
- --- 6191,6231 ----
- third_reload_reg)));
- }
- else
- + /* intel1 */
- + reload_insn =
- gen_reload (second_reload_reg, oldequiv,
- reload_opnum[j],
- ! reload_when_needed[j]);
- ! /* intel1 */
- ! if ((flag_loop_after_global ||flag_peep_spills)
- ! &&is_a_reload_stack_slot(oldequiv,&indx,cur_stack_offset,NULL))
- ! {
- ! RTX_IS_SPILL_P (reload_insn) = 1;
- ! if (indx == -1)
- ! {
- ! tmp_stack_slot
- ! = eliminate_regs (
- ! reg_equiv_memory_loc[REGNO (oldequiv)],
- ! GET_MODE (oldequiv), NULL_RTX);
- !
- ! if (num_reload_stack_slots < MAX_RELOAD_ STACK_SLOTS
- ! && !is_a_reload_stack_slot (tmp_stack_slot, &indx, cur_stack_offset, NULL))
- ! {
- ! reload_slots[num_reload_stack_slots].cur_stack_offset
- ! = cur_stack_offset;
- ! reload_slots[num_reload_stack_slots].stack_slot_pseudo_reg
- ! = REGNO (oldequiv);
- ! reload_slots[num_reload_stack_slots].reload_stack_slot
- ! = tmp_stack_slot;
- ! reload_slots[num_reload_stack_slots++].reload_insn
- ! = NULL;
- ! }
- ! SPILL_PSEUDO (reload_insn) = REGNO (oldequiv);
- ! }
- ! else
- ! SPILL_PSEUDO (reload_insn)
- ! = reload_slots[indx].stack_slot_pseudo_reg;
- ! }
-
- oldequiv = second_reload_reg;
- }
- ***************
- *** 6065,6072 ****
- #endif
-
- if (! special && ! rtx_equal_p (reloadreg, oldequiv))
- ! gen_reload (reloadreg, oldequiv, reload_opnum[j],
- reload_when_needed[j]);
-
- #if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P)
- /* We may have to make a REG_DEAD note for the secondary reload
- --- 6234,6271 ----
- #endif
-
- if (! special && ! rtx_equal_p (reloadreg, oldequiv))
- ! /* intel1 */
- ! reload_insn = gen_reload (reloadreg, oldequiv, reload_opnum[j],
- reload_when_needed[j]);
- + /* intel1 */ if ((flag_loop_after_global || flag_peep_spills)
- + && is_a_reload_stack_slot (oldequiv, &indx, cur_stack_offset, NULL))
- + {
- + RTX_IS_SPILL_P (reload_insn) = 1;
- + if (indx == -1)
- + {
- + tmp_stack_slot
- + = eliminate_regs (
- + reg_equiv_memory_loc[REGNO (oldequiv)],
- + GET_MODE (oldequiv), NULL_RTX);
- +
- + if (num_reload_stack_slots < MAX_RELOAD_STACK_SLOTS
- + && !is_a_reload_stack_slot (tmp_stack_slot, &indx, cur_stack_offset, NULL))
- + {
- + reload_slots[num_reload_stack_slots].cur_stack_offset
- + = cur_stack_offset;
- + reload_slots[num_reload_stack_slots].stack_slot_pseudo_reg
- + = REGNO (oldequiv);
- + reload_slots[num_reload_stack_slots].reload_stack_slot
- + = tmp_stack_slot;
- + reload_slots[num_reload_stack_slots++].reload_insn
- + = NULL;
- + }
- + SPILL_PSEUDO (reload_insn) = REGNO (oldequiv);
- + }
- + else
- + SPILL_PSEUDO (reload_insn)
- + = reload_slots[indx].stack_slot_pseudo_reg;
- + }
-
- #if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P)
- /* We may have to make a REG_DEAD note for the secondary reload
- ***************
- *** 6260,6275 ****
- XEXP (note, 0) = reload_reg_rtx[j];
- continue;
- }
- - /* Likewise for a SUBREG of an operand that dies. */
- - else if (GET_CODE (old) == SUBREG
- - && GET_CODE (SUBREG_REG (old)) == REG
- - && 0 != (note = find_reg_note (insn, REG_UNUSED,
- - SUBREG_REG (old))))
- - {
- - XEXP (note, 0) = gen_lowpart_common (GET_MODE (old),
- - reload_reg_rtx[j]);
- - continue;
- - }
- else if (GET_CODE (old) == SCRATCH)
- /* If we aren't optimizing, there won't be a REG_UNUSED note,
- but we don't want to make an output reload. */
- --- 6459,6464 ----
- ***************
- *** 6289,6298 ****
- if (GET_CODE (insn) == JUMP_INSN)
- abort ();
-
- ! if (reload_when_needed[j] == RELOAD_OTHER)
- ! start_sequence ();
- ! else
- ! push_to_sequence (output_reload_insns[reload_opnum[j]]);
-
- /* Determine the mode to reload in.
- See comments above (for input reloading). */
- --- 6478,6484 ----
- if (GET_CODE (insn) == JUMP_INSN)
- abort ();
-
- ! push_to_sequence (output_reload_insns[reload_opnum[j]]);
-
- /* Determine the mode to reload in.
- See comments above (for input reloading). */
- ***************
- *** 6358,6380 ****
- {
- rtx third_reloadreg
- = reload_reg_rtx[reload_secondary_out_reload[secondary_reload]];
- - rtx tem;
-
- /* Copy primary reload reg to secondary reload reg.
- (Note that these have been swapped above, then
- secondary reload reg to OLD using our insn. */
-
- - /* If REAL_OLD is a paradoxical SUBREG, remove it
- - and try to put the opposite SUBREG on
- - RELOADREG. */
- - if (GET_CODE (real_old) == SUBREG
- - && (GET_MODE_SIZE (GET_MODE (real_old))
- - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (real_old))))
- - && 0 != (tem = gen_lowpart_common
- - (GET_MODE (SUBREG_REG (real_old)),
- - reloadreg)))
- - real_old = SUBREG_REG (real_old), reloadreg = tem;
- -
- gen_reload (reloadreg, second_reloadreg,
- reload_opnum[j], reload_when_needed[j]);
- emit_insn ((GEN_FCN (tertiary_icode)
- --- 6544,6554 ----
- ***************
- *** 6392,6402 ****
- --- 6566,6612 ----
- }
- }
- #endif
- + /* PROBLEM: supposed to be intel code here, but too much has
- + changed above, I don't know how it maps */
-
- /* Output the last reload insn. */
- if (! special)
- + /*
- gen_reload (old, reloadreg, reload_opnum[j],
- reload_when_needed[j]);
- + */
- + {
- + emit_insn(gen_move_insn(old,reloadreg));
- + /* intel1 */ if ((flag_loop_after_global || flag_peep_spills)
- + && is_a_reload_stack_slot (old, &indx, cur_stack_offset, NULL))
- + {
- + reload_insn = get_last_insn ();
- + RTX_IS_SPILL_P ( reload_insn) = 1;
- + if (indx == -1)
- + {
- + tmp_stack_slot = eliminate_regs (
- + reg_equiv_memory_loc[REGNO (old)],
- + GET_MODE (old), NULL_RTX);
- +
- + if (num_reload_stack_slots < MAX_RELOAD_STACK_SLOTS
- + && !is_a_reload_stack_slot (tmp_stack_slot, &indx,
- + cur_stack_offset, NULL))
- + {
- + reload_slots[num_reload_stack_slots].cur_stack_offset
- + = cur_stack_offset;
- + reload_slots[num_reload_stack_slots].stack_slot_pseudo_reg
- + = REGNO (old);
- + reload_slots[num_reload_stack_slots].reload_stack_slot
- + = tmp_stack_slot;
- + reload_slots[num_reload_stack_slots++].reload_insn = NULL;
- + }
- + SPILL_PSEUDO (reload_insn) = REGNO (old);
- + } else
- + SPILL_PSEUDO (reload_insn)
- + = reload_slots[indx].stack_slot_pseudo_reg;
- + }
- + }
- +
-
- #ifdef PRESERVE_DEATH_INFO_REGNO_P
- /* If final will look at death notes for this reg,
- ***************
- *** 6436,6450 ****
- new_spill_reg_store[reload_spill_index[j]] = p;
- }
-
- ! if (reload_when_needed[j] == RELOAD_OTHER)
- ! {
- ! if (other_output_reload_insns)
- ! emit_insns (other_output_reload_insns);
- ! other_output_reload_insns = get_insns ();
- ! }
- ! else
- ! output_reload_insns[reload_opnum[j]] = get_insns ();
- !
- end_sequence ();
- }
- }
- --- 6646,6652 ----
- new_spill_reg_store[reload_spill_index[j]] = p;
- }
-
- ! output_reload_insns[reload_opnum[j]] = get_insns ();
- end_sequence ();
- }
- }
- ***************
- *** 6455,6461 ****
-
- RELOAD_FOR_OTHER_ADDRESS reloads for input addresses.
-
- ! RELOAD_OTHER reloads, output in ascending order by reload number.
-
- For each operand, any RELOAD_FOR_INPUT_ADDRESS reloads followed by
- the RELOAD_FOR_INPUT reload for the operand.
- --- 6657,6663 ----
-
- RELOAD_FOR_OTHER_ADDRESS reloads for input addresses.
-
- ! RELOAD_OTHER reloads.
-
- For each operand, any RELOAD_FOR_INPUT_ADDRESS reloads followed by
- the RELOAD_FOR_INPUT reload for the operand.
- ***************
- *** 6467,6476 ****
- After the insn being reloaded, we write the following:
-
- For each operand, any RELOAD_FOR_OUTPUT_ADDRESS reload followed by
- ! the RELOAD_FOR_OUTPUT reload for that operand.
- !
- ! Any RELOAD_OTHER output reloads, output in descending order by
- ! reload number. */
-
- emit_insns_before (other_input_address_reload_insns, before_insn);
- emit_insns_before (other_input_reload_insns, before_insn);
- --- 6669,6675 ----
- After the insn being reloaded, we write the following:
-
- For each operand, any RELOAD_FOR_OUTPUT_ADDRESS reload followed by
- ! the RELOAD_FOR_OUTPUT reload for that operand. */
-
- emit_insns_before (other_input_address_reload_insns, before_insn);
- emit_insns_before (other_input_reload_insns, before_insn);
- ***************
- *** 6490,6497 ****
- emit_insns_before (output_reload_insns[j], following_insn);
- }
-
- - emit_insns_before (other_output_reload_insns, following_insn);
- -
- /* Move death notes from INSN
- to output-operand-address and output reload insns. */
- #ifdef PRESERVE_DEATH_INFO_REGNO_P
- --- 6689,6694 ----
- ***************
- *** 6691,6696 ****
- --- 6888,6895 ----
- int opnum;
- enum reload_type type;
- {
- + /* intel1 */
- + int indx;
- rtx last = get_last_insn ();
- rtx tem;
-
- ***************
- *** 6858,6864 ****
- --- 7057,7080 ----
-
- /* If IN is a simple operand, use gen_move_insn. */
- else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG)
- + {
- emit_insn (gen_move_insn (out, in));
- + if ((flag_loop_after_global || flag_peep_spills) /* intel1 */
- + && is_a_reload_stack_slot (in, &indx, cur_stack_offset, get_last_insn()))
- + {
- + rtx reload_insn = get_last_insn ();
- +
- + RTX_IS_SPILL_P ( reload_insn) = 1;
- + if (indx == -1)
- + {
- + SPILL_PSEUDO (reload_insn) = REGNO (in);
- + }
- + else
- + SPILL_PSEUDO (reload_insn)
- + = reload_slots[indx].stack_slot_pseudo_reg;
- + }
- + }
- +
-
- #ifdef HAVE_reload_load_address
- else if (HAVE_reload_load_address)
- ***************
- *** 7173,7176 ****
- --- 7389,7643 ----
- }
- }
- return count;
- + }
- +
- + /* intel1 */
- +
- + /* return 1 if rx is a stack slot */
- + int
- + is_a_stack_slot (rx)
- + rtx rx;
- + {
- + if (GET_CODE (rx) != MEM)
- + {
- + return (0);
- + }
- + if (GET_CODE (XEXP (rx, 0)) == PLUS
- + && XEXP ( XEXP (rx, 0), 0) == stack_pointer_rtx
- + && !frame_pointer_needed)
- + {
- + if ( GET_CODE (XEXP ( XEXP (rx, 0), 1)) == CONST_INT)
- + {
- + return (1);
- + }
- + else
- + {
- + return (0);
- + }
- + }
- + else if (GET_CODE (XEXP (rx, 0)) == PLUS
- + && XEXP ( XEXP (rx, 0), 0) == frame_pointer_rtx
- + && frame_pointer_needed)
- + {
- + if ( GET_CODE (XEXP ( XEXP (rx, 0), 1)) == CONST_INT)
- + {
- + return (1);
- + }
- + else
- + {
- + return (0);
- + }
- + }
- + else if ((XEXP (rx, 0) == frame_pointer_rtx && frame_pointer_needed)
- + || (XEXP (rx, 0) == stack_pointer_rtx && ! frame_pointer_needed))
- + {
- + return (1);
- + }
- + else
- + {
- + return (0);
- + }
- +
- + }
- +
- + /*
- + if rx is a reload slot then set *indx to the index in the
- + reload_slots array which contains it and return 1
- + else
- + return 0
- + */
- +
- + int
- + is_a_reload_stack_slot (rx, indx, cur_stack_offset, reload_insn)
- + rtx rx;
- + int *indx;
- + int cur_stack_offset;
- + rtx reload_insn;
- + {
- + int i, is_based_on_stack_pointer, stack_offset, stack_i_offset;
- + rtx stack_slot_i;
- +
- +
- + if (GET_CODE (rx) == REG && REGNO (rx) >= FIRST_PSEUDO_REGISTER
- + && pseudo_spilled[REGNO (rx)])
- + {
- + *indx = -1;
- + return (1);
- + }
- + if (GET_CODE (rx) == SUBREG
- + && GET_CODE (SUBREG_REG (rx)) == MEM)
- + {
- + return (is_a_reload_stack_slot (SUBREG_REG (rx), indx,
- + cur_stack_offset, reload_insn));
- + }
- + if (GET_CODE (rx) != MEM)
- + {
- + return (0);
- + }
- + is_based_on_stack_pointer = 0;
- + if (GET_CODE (XEXP (rx, 0)) == PLUS
- + && XEXP ( XEXP (rx, 0), 0) == stack_pointer_rtx
- + && !frame_pointer_needed)
- + {
- + is_based_on_stack_pointer = 1;
- + if ( GET_CODE (XEXP ( XEXP (rx, 0), 1)) == CONST_INT)
- + {
- + stack_offset = XINT (XEXP ( XEXP (rx, 0), 1), 0);
- + }
- + else
- + {
- + return (0);
- + }
- + }
- + else if (GET_CODE (XEXP (rx, 0)) == PLUS
- + && XEXP ( XEXP (rx, 0), 0) == frame_pointer_rtx
- + && frame_pointer_needed)
- + {
- + if ( GET_CODE (XEXP ( XEXP (rx, 0), 1)) == CONST_INT)
- + {
- + ;
- + }
- + else
- + {
- + return (0);
- + }
- + }
- + else if ((XEXP (rx, 0) == frame_pointer_rtx && frame_pointer_needed)
- + || (XEXP (rx, 0) == stack_pointer_rtx && ! frame_pointer_needed))
- + {
- + is_based_on_stack_pointer = (XEXP (rx, 0) == stack_pointer_rtx );
- + }
- + else
- + {
- + return (0);
- + }
- +
- +
- + for (i = 0; i < num_reload_stack_slots; i++)
- + {
- + if (!is_based_on_stack_pointer)
- + {
- + if ((reload_insn == NULL || reload_insn == reload_slots[i].reload_insn)
- + && rtx_equal_p (XEXP (reload_slots[i].reload_stack_slot, 0),
- + XEXP (rx, 0)))
- + {
- + *indx = i;
- + return (1);
- + }
- + }
- + else
- + {
- + stack_slot_i = XEXP (reload_slots[i].reload_stack_slot, 0);
- + if (GET_CODE (stack_slot_i) == PLUS
- + && XEXP ( stack_slot_i, 0) == stack_pointer_rtx)
- + {
- + if ( GET_CODE (XEXP ( stack_slot_i, 1)) == CONST_INT)
- + {
- + stack_i_offset = XINT (XEXP ( stack_slot_i, 1), 0);
- + }
- + else
- + {
- + abort ();
- + }
- + }
- + else if (stack_slot_i == stack_pointer_rtx)
- + {
- + stack_i_offset = 0;
- + }
- + else
- + {
- + abort ();
- + }
- + stack_i_offset -= reload_slots[i].cur_stack_offset;
- + if ((reload_insn == NULL || reload_insn == reload_slots[i].reload_insn)
- + && (stack_offset - cur_stack_offset == stack_i_offset))
- + {
- + *indx = i;
- + return (1);
- + }
- + }
- + }
- + return (0);
- + }
- +
- +
- + int
- + are_same_reload_slots (slot1, offset1, slot2, offset2)
- + rtx slot1, slot2;
- + int offset1, offset2;
- + {
- + rtx base_reg1, base_reg2;
- + int add_val1, add_val2;
- +
- + if (GET_CODE (XEXP (slot1, 0)) == PLUS)
- + {
- + if (GET_CODE (XEXP (XEXP (slot1, 0), 0)) == REG)
- + {
- + base_reg1 = XEXP (XEXP (slot1, 0), 0);
- + if (GET_CODE (XEXP (XEXP (slot1, 0), 1)) == CONST_INT)
- + {
- + add_val1 = XINT (XEXP (XEXP (slot1, 0), 1), 0);
- + }
- + }
- + }
- + else
- + {
- + add_val1 = 0;
- + base_reg1 = XEXP (slot1, 0);
- + }
- +
- + if (GET_CODE (XEXP (slot2, 0)) == PLUS)
- + {
- + if (GET_CODE (XEXP (XEXP (slot2, 0), 0)) == REG)
- + {
- + base_reg2 = XEXP (XEXP (slot2, 0), 0);
- + if (GET_CODE (XEXP (XEXP (slot2, 0), 1)) == CONST_INT)
- + {
- + add_val2 = XINT (XEXP (XEXP (slot2, 0), 1), 0);
- + }
- + }
- + }
- + else
- + {
- + add_val2 = 0;
- + base_reg2 = XEXP (slot2, 0);
- + }
- + if (base_reg1 == frame_pointer_rtx)
- + {
- + offset1 = 0;
- + }
- + if (base_reg2 == frame_pointer_rtx)
- + {
- + offset2 = 0;
- + }
- + if (base_reg1 == base_reg2
- + && ((add_val1 - offset1) == (add_val2 - offset2)))
- + {
- + return (1);
- + }
- + return (0);
- + }
- +
- + /*
- + if x refernces a paramater then return 1
- + else return 0
- + */
- +
- + int
- + is_a_param_slot (x)
- + rtx x;
- + {
- + if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS
- + && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
- + && REGNO (XEXP (XEXP (x, 0), 0)) == ARG_POINTER_REGNUM
- + && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
- + {
- + return (1);
- + }
- + if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG
- + && REGNO (XEXP (x, 0)) == ARG_POINTER_REGNUM)
- + {
- + return (1);
- + }
- + return (0);
- }
- diff -rNci gcc-2.7.2/reorg.c gcc-2.7.2p/reorg.c
- *** gcc-2.7.2/reorg.c Fri Sep 15 21:38:55 1995
- --- gcc-2.7.2p/reorg.c Thu Jun 15 12:02:32 1995
- ***************
- *** 2857,2880 ****
- && eligible_for_delay (insn, slots_filled, trial, flags)
- && no_labels_between_p (insn, trial))
- {
- - rtx *tmp;
- slots_filled++;
- delay_list = add_to_delay_list (trial, delay_list);
- -
- - /* TRIAL may have had its delay slot filled, then unfilled. When
- - the delay slot is unfilled, TRIAL is placed back on the unfilled
- - slots obstack. Unfortunately, it is placed on the end of the
- - obstack, not in its original location. Therefore, we must search
- - from entry i + 1 to the end of the unfilled slots obstack to
- - try and find TRIAL. */
- - tmp = &unfilled_slots_base[i + 1];
- - while (*tmp != trial && tmp != unfilled_slots_next)
- - tmp++;
- -
- /* Remove the unconditional jump from consideration for delay slot
- ! filling and unthread it. */
- ! if (*tmp == trial)
- ! *tmp = 0;
- {
- rtx next = NEXT_INSN (trial);
- rtx prev = PREV_INSN (trial);
- --- 2857,2868 ----
- && eligible_for_delay (insn, slots_filled, trial, flags)
- && no_labels_between_p (insn, trial))
- {
- slots_filled++;
- delay_list = add_to_delay_list (trial, delay_list);
- /* Remove the unconditional jump from consideration for delay slot
- ! filling and unthread it. */
- ! if (unfilled_slots_base[i + 1] == trial)
- ! unfilled_slots_base[i + 1] = 0;
- {
- rtx next = NEXT_INSN (trial);
- rtx prev = PREV_INSN (trial);
- ***************
- *** 2974,2985 ****
- is a CALL_INSN (or a CALL_INSN is passed), cannot trap (because the
- call might not return).
-
- ! There used to be code which continued past the target label if
- ! we saw all uses of the target label. This code did not work,
- ! because it failed to account for some instructions which were
- ! both annulled and marked as from the target. This can happen as a
- ! result of optimize_skip. Since this code was redundant with
- ! fill_eager_delay_slots anyways, it was just deleted. */
-
- if (slots_filled != slots_to_fill
- && (GET_CODE (insn) != JUMP_INSN
- --- 2962,2975 ----
- is a CALL_INSN (or a CALL_INSN is passed), cannot trap (because the
- call might not return).
-
- ! If this is a conditional jump, see if it merges back to us early
- ! enough for us to pick up insns from the merge point. Don't do
- ! this if there is another branch to our label unless we pass all of
- ! them.
- !
- ! Another similar merge is if we jump to the same place that a
- ! later unconditional jump branches to. In that case, we don't
- ! care about the number of uses of our label. */
-
- if (slots_filled != slots_to_fill
- && (GET_CODE (insn) != JUMP_INSN
- ***************
- *** 2989,2994 ****
- --- 2979,2986 ----
- {
- rtx target = 0;
- int maybe_never = 0;
- + int passed_label = 0;
- + int target_uses;
- struct resources needed_at_jump;
-
- CLEAR_RESOURCE (&needed);
- ***************
- *** 3005,3011 ****
- mark_set_resources (insn, &set, 0, 1);
- mark_referenced_resources (insn, &needed, 1);
- if (GET_CODE (insn) == JUMP_INSN)
- ! target = JUMP_LABEL (insn);
- }
-
- for (trial = next_nonnote_insn (insn); trial; trial = next_trial)
- --- 2997,3009 ----
- mark_set_resources (insn, &set, 0, 1);
- mark_referenced_resources (insn, &needed, 1);
- if (GET_CODE (insn) == JUMP_INSN)
- ! {
- ! /* Get our target and show how many more uses we want to
- ! see before we hit the label. */
- ! target = JUMP_LABEL (insn);
- ! target_uses = LABEL_NUSES (target) - 1;
- ! }
- !
- }
-
- for (trial = next_nonnote_insn (insn); trial; trial = next_trial)
- ***************
- *** 3014,3021 ****
-
- next_trial = next_nonnote_insn (trial);
-
- ! if (GET_CODE (trial) == CODE_LABEL
- ! || GET_CODE (trial) == BARRIER)
- break;
-
- /* We must have an INSN, JUMP_INSN, or CALL_INSN. */
- --- 3012,3033 ----
-
- next_trial = next_nonnote_insn (trial);
-
- ! if (GET_CODE (trial) == CODE_LABEL)
- ! {
- ! passed_label = 1;
- !
- ! /* If this is our target, see if we have seen all its uses.
- ! If so, indicate we have passed our target and ignore it.
- ! All other labels cause us to stop our search. */
- ! if (trial == target && target_uses == 0)
- ! {
- ! target = 0;
- ! continue;
- ! }
- ! else
- ! break;
- ! }
- ! else if (GET_CODE (trial) == BARRIER)
- break;
-
- /* We must have an INSN, JUMP_INSN, or CALL_INSN. */
- ***************
- *** 3040,3046 ****
- {
- if (target == 0)
- break;
- ! else if (JUMP_LABEL (trial_delay) != target)
- {
- mark_target_live_regs
- (next_active_insn (JUMP_LABEL (trial_delay)),
- --- 3052,3060 ----
- {
- if (target == 0)
- break;
- ! else if (JUMP_LABEL (trial_delay) == target)
- ! target_uses--;
- ! else
- {
- mark_target_live_regs
- (next_active_insn (JUMP_LABEL (trial_delay)),
- ***************
- *** 3073,3078 ****
- --- 3087,3094 ----
- link_cc0_insns (trial);
- #endif
-
- + if (passed_label)
- + update_block (trial, trial);
- delete_insn (trial);
- if (slots_to_fill == ++slots_filled)
- break;
- ***************
- *** 3398,3405 ****
- trial = try_split (pat, trial, 0);
- if (new_thread == old_trial)
- new_thread = trial;
- - if (thread == old_trial)
- - thread = trial;
- pat = PATTERN (trial);
- if ((thread_if_true
- ? eligible_for_annul_false (insn, *pslots_filled, trial, flags)
- --- 3414,3419 ----
- ***************
- *** 3663,3669 ****
- if (condition == 0)
- continue;
-
- ! /* Get the next active fallthrough and target insns and see if we own
- them. Then see whether the branch is likely true. We don't need
- to do a lot of this for unconditional branches. */
-
- --- 3677,3683 ----
- if (condition == 0)
- continue;
-
- ! /* Get the next active fallthough and target insns and see if we own
- them. Then see whether the branch is likely true. We don't need
- to do a lot of this for unconditional branches. */
-
- diff -rNci gcc-2.7.2/rtl.c gcc-2.7.2p/rtl.c
- *** gcc-2.7.2/rtl.c Thu Jun 15 12:02:59 1995
- --- gcc-2.7.2p/rtl.c Tue Jan 23 09:25:31 1996
- ***************
- *** 174,184 ****
- "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
- "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG"};
-
- char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
- "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
- "REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
- "REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
- ! "REG_DEP_ANTI", "REG_DEP_OUTPUT" };
-
- /* Allocate an rtx vector of N elements.
- Store the length, and initialize all elements to zero. */
- --- 174,185 ----
- "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
- "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG"};
-
- + /* intel1 added REG_DEP_TMP */
- char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
- "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
- "REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
- "REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
- ! "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_DEP_TMP" };
-
- /* Allocate an rtx vector of N elements.
- Store the length, and initialize all elements to zero. */
- ***************
- *** 302,307 ****
- --- 303,310 ----
- copy->volatil = orig->volatil;
- copy->unchanging = orig->unchanging;
- copy->integrated = orig->integrated;
- + /* intel1 */
- + copy->is_spill_rtx = orig->is_spill_rtx;
-
- format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
-
- diff -rNci gcc-2.7.2/rtl.def gcc-2.7.2p/rtl.def
- *** gcc-2.7.2/rtl.def Thu Jun 15 12:03:32 1995
- --- gcc-2.7.2p/rtl.def Tue Jan 23 09:25:31 1996
- ***************
- *** 347,353 ****
- ---------------------------------------------------------------------- */
-
- /* An instruction that cannot jump. */
- ! DEF_RTL_EXPR(INSN, "insn", "iuueiee", 'i')
-
- /* An instruction that can possibly jump.
- Fields ( rtx->fld[] ) have exact same meaning as INSN's. */
- --- 347,354 ----
- ---------------------------------------------------------------------- */
-
- /* An instruction that cannot jump. */
- ! /* intel1 added last 0 - this field is used in scheduling */
- ! DEF_RTL_EXPR(INSN, "insn", "iuueiee0", 'i')
-
- /* An instruction that can possibly jump.
- Fields ( rtx->fld[] ) have exact same meaning as INSN's. */
- ***************
- *** 644,650 ****
-
- /* Operand:
- 0: value to be shifted.
- ! 1: number of bits. */
- DEF_RTL_EXPR(ASHIFT, "ashift", "ee", '2')
- DEF_RTL_EXPR(ROTATE, "rotate", "ee", '2')
-
- --- 645,655 ----
-
- /* Operand:
- 0: value to be shifted.
- ! 1: number of bits.
- ! ASHIFT and LSHIFT are distinguished because on some machines
- ! these allow a negative operand and shift right in that case.
- ! */
- ! DEF_RTL_EXPR(LSHIFT, "lshift", "ee", '2')
- DEF_RTL_EXPR(ASHIFT, "ashift", "ee", '2')
- DEF_RTL_EXPR(ROTATE, "rotate", "ee", '2')
-
- diff -rNci gcc-2.7.2/rtl.h gcc-2.7.2p/rtl.h
- *** gcc-2.7.2/rtl.h Thu Jun 15 12:03:16 1995
- --- gcc-2.7.2p/rtl.h Tue Jan 23 09:25:31 1996
- ***************
- *** 140,145 ****
- --- 140,148 ----
- In a REG, nonzero means this reg refers to the return value
- of the current function. */
- unsigned integrated : 1;
- + /* intel1 Nonzero if this rtx is a spill rtx */
- + /* intel2 overlap: Nonzero if this rtx was created by memory_simplify */
- + unsigned is_spill_rtx: 1;
- /* The first element of the operands of this rtx.
- The number of operands and their types are controlled
- by the `code' field, according to rtl.def. */
- ***************
- *** 211,216 ****
- --- 214,223 ----
-
- #define RTX_INTEGRATED_P(RTX) ((RTX)->integrated)
- #define RTX_UNCHANGING_P(RTX) ((RTX)->unchanging)
- + /* intel1 */
- + #define RTX_IS_SPILL_P(RTX) ((RTX)->is_spill_rtx)
- + /* intel2 - see a note above (for is_spill_rtx field) */
- + #define RTX_IS_RISC_P(RTX) ((RTX)->is_spill_rtx)
-
- /* RTL vector. These appear inside RTX's when there is a need
- for a variable number of things. The principle use is inside
- ***************
- *** 259,264 ****
- --- 266,276 ----
- #define PREV_INSN(INSN) ((INSN)->fld[1].rtx)
- #define NEXT_INSN(INSN) ((INSN)->fld[2].rtx)
-
- + /* intel1 used in sched*/
- + #define ORG_NEXT_INSN(INSN) ((INSN)->fld[7].rtx)
- + /* intel1 used in (loop) opt of spills */
- + #define SPILL_PSEUDO(INSN) ((INSN)->fld[7].rtint)
- +
- /* The body of an insn. */
- #define PATTERN(INSN) ((INSN)->fld[3].rtx)
-
- ***************
- *** 348,354 ****
- REG_EQUAL = 5, REG_RETVAL = 6, REG_LIBCALL = 7,
- REG_NONNEG = 8, REG_NO_CONFLICT = 9, REG_UNUSED = 10,
- REG_CC_SETTER = 11, REG_CC_USER = 12, REG_LABEL = 13,
- ! REG_DEP_ANTI = 14, REG_DEP_OUTPUT = 15 };
-
- /* Define macros to extract and insert the reg-note kind in an EXPR_LIST. */
- #define REG_NOTE_KIND(LINK) ((enum reg_note) GET_MODE (LINK))
- --- 360,366 ----
- REG_EQUAL = 5, REG_RETVAL = 6, REG_LIBCALL = 7,
- REG_NONNEG = 8, REG_NO_CONFLICT = 9, REG_UNUSED = 10,
- REG_CC_SETTER = 11, REG_CC_USER = 12, REG_LABEL = 13,
- ! REG_DEP_ANTI = 14, REG_DEP_OUTPUT = 15, REG_DEP_TMP = 16 };
-
- /* Define macros to extract and insert the reg-note kind in an EXPR_LIST. */
- #define REG_NOTE_KIND(LINK) ((enum reg_note) GET_MODE (LINK))
- diff -rNci gcc-2.7.2/rtlanal.c gcc-2.7.2p/rtlanal.c
- *** gcc-2.7.2/rtlanal.c Fri Oct 6 17:13:57 1995
- --- gcc-2.7.2p/rtlanal.c Thu Jun 15 12:03:58 1995
- ***************
- *** 428,435 ****
- static rtx reg_set_reg;
- static int reg_set_flag;
-
- ! static void
- ! reg_set_p_1 (x, pat)
- rtx x;
- {
- /* We don't want to return 1 if X is a MEM that contains a register
- --- 428,435 ----
- static rtx reg_set_reg;
- static int reg_set_flag;
-
- ! void
- ! reg_set_p_1 (x)
- rtx x;
- {
- /* We don't want to return 1 if X is a MEM that contains a register
- ***************
- *** 905,911 ****
- || ((GET_CODE (reg_set_last_value) == REG
- || GET_CODE (reg_set_last_value) == SUBREG)
- && ! reg_set_between_p (reg_set_last_value,
- ! insn, orig_insn)))
- return reg_set_last_value;
- else
- return 0;
- --- 905,911 ----
- || ((GET_CODE (reg_set_last_value) == REG
- || GET_CODE (reg_set_last_value) == SUBREG)
- && ! reg_set_between_p (reg_set_last_value,
- ! NEXT_INSN (insn), orig_insn)))
- return reg_set_last_value;
- else
- return 0;
- diff -rNci gcc-2.7.2/scan-decls.c gcc-2.7.2p/scan-decls.c
- *** gcc-2.7.2/scan-decls.c Mon Jun 19 18:18:43 1995
- --- gcc-2.7.2p/scan-decls.c Thu Jun 15 12:04:57 1995
- ***************
- *** 246,252 ****
- break;
-
- default:
- ! prev_id_start = 0;
- }
- }
- }
- --- 246,252 ----
- break;
-
- default:
- ! prev_id_start = NULL;
- }
- }
- }
- diff -rNci gcc-2.7.2/sched.c gcc-2.7.2p/sched.c
- *** gcc-2.7.2/sched.c Thu Jun 15 12:06:39 1995
- --- gcc-2.7.2p/sched.c Tue Jan 30 21:06:34 1996
- ***************
- *** 125,131 ****
- --- 125,153 ----
- #include "insn-config.h"
- #include "insn-attr.h"
-
- + /* intel1 */
- + #ifndef STACK_PUSH_CODE
- + #ifdef STACK_GROWS_DOWNWARD
- + #define STACK_PUSH_CODE PRE_DEC
- + #else
- + #define STACK_PUSH_CODE PRE_INC
- + #endif
- + #endif
- #ifdef INSN_SCHEDULING
- + /* intel1 */
- + #ifndef STACK_PUSH_CODE
- + #ifdef STACK_GROWS_DOWNWARD
- + #define STACK_PUSH_CODE PRE_DEC
- + #else
- + #define STACK_PUSH_CODE PRE_INC
- + #endif
- + #endif
- + #ifdef SMALL_REGISTER_CLASSES
- + /* can't move anything past a hard register */
- + static rtx first_insn_to_pivot;
- + static rtx last_hard_reg_insn;
- + #endif
- +
- /* Arrays set up by scheduling for the same respective purposes as
- similar-named arrays set up by flow analysis. We work with these
- arrays during the scheduling pass so we can compare values against
- ***************
- *** 146,151 ****
- --- 168,184 ----
- static regset reg_pending_sets;
- static int reg_pending_sets_all;
-
- + /* intel1 */
- + #ifdef NO_STACK_REG_REORDER
- + /* don't reorder insns that refernce stack registers */
- + static rtx prev_stack_reg_insn = NULL;
- + #endif
- + /* intel1 */
- + #ifdef STACK_REGS
- + static int maintain_order = 0;
- + #endif
- + static FILE * cur_dump_file;
- +
- /* Vector indexed by INSN_UID giving the original ordering of the insns. */
- static int *insn_luid;
- #define INSN_LUID(INSN) (insn_luid[INSN_UID (INSN)])
- ***************
- *** 293,305 ****
- };
-
- /* Forward declarations. */
- static rtx canon_rtx PROTO((rtx));
- static int rtx_equal_for_memref_p PROTO((rtx, rtx));
- static rtx find_symbolic_term PROTO((rtx));
- static int memrefs_conflict_p PROTO((int, rtx, int, rtx,
- HOST_WIDE_INT));
- static void add_dependence PROTO((rtx, rtx, enum reg_note));
- ! static void remove_dependence PROTO((rtx, rtx));
- static rtx find_insn_list PROTO((rtx, rtx));
- static int insn_unit PROTO((rtx));
- static unsigned int blockage_range PROTO((int, rtx));
- --- 326,342 ----
- };
-
- /* Forward declarations. */
- +
- + /* intel1 */
- + static int is_part_of_group PROTO((rtx, rtx));
- + static int prev_insts_in_block PROTO((int, rtx));
- static rtx canon_rtx PROTO((rtx));
- static int rtx_equal_for_memref_p PROTO((rtx, rtx));
- static rtx find_symbolic_term PROTO((rtx));
- static int memrefs_conflict_p PROTO((int, rtx, int, rtx,
- HOST_WIDE_INT));
- static void add_dependence PROTO((rtx, rtx, enum reg_note));
- ! void remove_dependence PROTO((rtx, rtx));
- static rtx find_insn_list PROTO((rtx, rtx));
- static int insn_unit PROTO((rtx));
- static unsigned int blockage_range PROTO((int, rtx));
- ***************
- *** 629,634 ****
- --- 666,906 ----
- else
- y = canon_rtx (y);
-
- + /* intel1
- + Missing special handling of a push onto the stack. */
- + if (reload_completed
- + &&
- + (GET_CODE (x) == STACK_PUSH_CODE
- + && XEXP (x, 0) == stack_pointer_rtx)
- + ||
- + (GET_CODE (y) == STACK_PUSH_CODE
- + && XEXP (y, 0) == stack_pointer_rtx)
- + )
- + {
- + rtx *push, *non_push;
- +
- + if (GET_CODE (x) == STACK_PUSH_CODE
- + && XEXP (x, 0) == stack_pointer_rtx)
- + {
- + push = &x;
- + non_push = &y;
- + }
- + else
- + {
- + push = &y;
- + non_push = &x;
- + }
- + if (find_symbolic_term (*non_push) != NULL)
- + { /* push onto stack does not conflict with global */
- + return (0);
- + }
- + if (RTX_IS_SPILL_P (*non_push))
- + { /* push onto stack does not overlap with spill slot */
- + return (0);
- + }
- + /* Check to see if the non push is a stack slot */
- + if (c == 0 && GET_CODE (*non_push) == PLUS
- + && XEXP ( *non_push, 0) == stack_pointer_rtx
- + && !frame_pointer_needed)
- + {
- + if ( GET_CODE (XEXP ( *non_push, 1)) == CONST_INT
- + && XINT (XEXP (*non_push, 1), 0)
- + > GET_MODE_SIZE (GET_MODE (*push)))
- + {
- + return (0);
- + }
- + }
- + else if (c == 0 && GET_CODE (*non_push) == PLUS
- + && XEXP ( *non_push, 0) == frame_pointer_rtx
- + && frame_pointer_needed)
- + {
- + if ( GET_CODE (XEXP ( *non_push, 1)) == CONST_INT)
- + {
- + return (0); /* Definitely not the same as the push if
- + frame_pointer is used. */
- + }
- + }
- + }
- +
- +
- + /* intel1
- + Missing handling of a spill slot - can't conflict with anything
- + that is not a spill slot */
- + if (reload_completed && RTX_IS_SPILL_P (x) != RTX_IS_SPILL_P (y)
- + && !rtx_equal_p(x,y) /*just to be safe */)
- + { /* Actually some spill slots are not being marked at present -
- + but no non spill slots are ever marked. So make sure
- + that the non spill slot does not overlap with spill slot */
- + rtx *spill, *non_spill;
- + int *spill_size, *non_spill_size, spill_offset, non_spill_offset,
- + spill_unknown, non_spill_unknown, maybe_spill;
- + spill_unknown = 0;
- + non_spill_unknown = 0;
- + maybe_spill = 0;
- + if (RTX_IS_SPILL_P (x))
- + {
- + spill = &x;
- + spill_size = &xsize;
- + non_spill = &y;
- + non_spill_size = &ysize;
- + }
- + else
- + {
- + spill = &y;
- + spill_size = &ysize;
- + non_spill = &x;
- + non_spill_size = &xsize;
- + }
- + if (GET_CODE (*non_spill) == PLUS)
- + {
- + if (GET_CODE (XEXP (*non_spill, 1)) == CONST_INT)
- + {
- + non_spill_offset = XINT (XEXP (*non_spill, 1), 0);
- + }
- + else
- + {
- + non_spill_unknown = 1;
- + }
- + if (GET_CODE (XEXP (*non_spill, 0)) == REG
- + && ((frame_pointer_needed && XEXP (*non_spill, 0) == frame_pointer_rtx)
- + || XEXP (*non_spill, 0) == stack_pointer_rtx))
- + {
- + maybe_spill = 1; /* It may overlap the spill slot */
- + }
- + }
- + else
- + if (GET_CODE (*non_spill) == REG
- + && ((frame_pointer_needed && *non_spill == frame_pointer_rtx)
- + || *non_spill == stack_pointer_rtx))
- + {
- + non_spill_offset = 0;
- + maybe_spill = 1;
- + }
- + if (maybe_spill == 0)
- + return (0);
- +
- + if (GET_CODE (*spill) == PLUS)
- + {
- + if (GET_CODE (XEXP (*spill, 1)) == CONST_INT)
- + {
- + spill_offset = XINT (XEXP (*spill, 1), 0);
- + }
- + else
- + {
- + spill_unknown = 1;
- + }
- + if (GET_CODE (XEXP (*spill, 0)) == REG
- + && ((frame_pointer_needed && XEXP (*spill, 0) == frame_pointer_rtx)
- + || XEXP (*spill, 0) == stack_pointer_rtx))
- + {
- + ; /* ok */
- + }
- + else
- + {
- + spill_unknown = 1;
- + }
- + }
- + else
- + if (GET_CODE (*spill) == REG
- + && ((frame_pointer_needed && *spill == frame_pointer_rtx)
- + || *spill == stack_pointer_rtx))
- + {
- + spill_offset = 0;
- + }
- + else
- + {
- + spill_unknown = 1;
- + }
- + if (non_spill_unknown == 0 && spill_unknown == 0)
- + {
- + if (non_spill_offset < spill_offset)
- + return (!(non_spill_offset + *non_spill_size <= spill_offset));
- + else
- + return (!(spill_offset + *spill_size <= non_spill_offset));
- + }
- + }
- +
- + /* intel1
- + Missing handling two spill slots conflict only if they overlap */
- + if (reload_completed && RTX_IS_SPILL_P (y) && RTX_IS_SPILL_P (x)
- + && c == 0
- + && !rtx_equal_p(y, x))
- + {
- + int x_offset, y_offset, x_unknown, y_unknown;
- + x_unknown = y_unknown = 0;
- + if (GET_CODE (x) == PLUS)
- + {
- + if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- + {
- + x_offset = XINT (XEXP (x, 1), 0);
- + }
- + else
- + {
- + x_unknown = 1;
- + }
- + if (GET_CODE (XEXP (x, 0)) == REG
- + && ((frame_pointer_needed && XEXP (x, 0) == frame_pointer_rtx)
- + || XEXP (x, 0) == stack_pointer_rtx))
- + {
- + ; /* ok */
- + }
- + else
- + {
- + x_unknown = 1;
- + }
- + }
- + else
- + if (GET_CODE (x) == REG
- + && ((frame_pointer_needed && x == frame_pointer_rtx)
- + || x == stack_pointer_rtx))
- + {
- + x_offset = 0;
- + }
- + else
- + {
- + x_unknown = 1;
- + }
- + if (GET_CODE (y) == PLUS)
- + {
- + if (GET_CODE (XEXP (y, 1)) == CONST_INT)
- + {
- + y_offset = XINT (XEXP (y, 1), 0);
- + }
- + else
- + {
- + y_unknown = 1;
- + }
- + if (GET_CODE (XEXP (y, 0)) == REG
- + && ((frame_pointer_needed && XEXP (y, 0) == frame_pointer_rtx)
- + || XEXP (y, 0) == stack_pointer_rtx))
- + {
- + ; /* ok */
- + }
- + else
- + {
- + y_unknown = 1;
- + }
- + }
- + else
- + if (GET_CODE (y) == REG
- + && ((frame_pointer_needed && y == frame_pointer_rtx)
- + || y == stack_pointer_rtx))
- + {
- + y_offset = 0;
- + }
- + else
- + {
- + y_unknown = 1;
- + }
- + if (x_unknown == 0 && y_unknown == 0)
- + {
- + if (x_offset < y_offset)
- + return (!(x_offset + xsize <= y_offset));
- + else
- + return (!(y_offset + ysize <= x_offset));
- + }
- + }
- +
- if (rtx_equal_for_memref_p (x, y))
- return (xsize == 0 || ysize == 0 ||
- (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
- ***************
- *** 922,928 ****
- --- 1194,1208 ----
- SCHED_GROUP_P. */
- while (NEXT_INSN (next) && SCHED_GROUP_P (NEXT_INSN (next))
- && GET_CODE (NEXT_INSN (next)) != CODE_LABEL)
- + {
- + /* intel1 - next might already be part of this SCHED_GROUP,
- + */
- + if(next==insn )
- + {
- + return;
- + }
- next = NEXT_INSN (next);
- + }
-
- /* Again, don't depend an insn on itself. */
- if (insn == next)
- ***************
- *** 956,962 ****
- /* Remove ELEM wrapped in an INSN_LIST from the LOG_LINKS
- of INSN. Abort if not found. */
-
- ! static void
- remove_dependence (insn, elem)
- rtx insn;
- rtx elem;
- --- 1236,1242 ----
- /* Remove ELEM wrapped in an INSN_LIST from the LOG_LINKS
- of INSN. Abort if not found. */
-
- ! void
- remove_dependence (insn, elem)
- rtx insn;
- rtx elem;
- ***************
- *** 1217,1225 ****
- --- 1497,1518 ----
- if (function_units[unit].blockage_range_function)
- {
- if (function_units[unit].blockage_function)
- + {
- + /* intel1 */
- + #ifdef ADJUST_BLOCKAGE
- + {
- + int blockage = (function_units[unit].blockage_function
- + (insn, unit_last_insn[instance]));
- + ADJUST_BLOCKAGE (unit_last_insn[instance], insn, blockage);
- + tick += blockage
- + - function_units[unit].max_blockage;
- + }
- + #else
- tick += (function_units[unit].blockage_function
- (insn, unit_last_insn[instance])
- - function_units[unit].max_blockage);
- + #endif
- + }
- else
- tick += ((int) MAX_BLOCKAGE_COST (blockage_range (unit, insn))
- - function_units[unit].max_blockage);
- ***************
- *** 1706,1711 ****
- --- 1999,2031 ----
- /* Function calls clobber all call_used regs. */
- add_dependence (insn, last_function_call, REG_DEP_ANTI);
- }
- + #ifdef SMALL_REGISTER_CLASSES
- + /* intel1
- + lifetime of hard registers must not be changed so this
- + insn becomes a pivot in the block.
- + */
- + if(reload_completed==0 && regno!=STACK_POINTER_REGNUM
- + && regno!=FRAME_POINTER_REGNUM)
- + {
- + rtx tinsn;
- +
- + tinsn = first_insn_to_pivot;
- + while(tinsn!=insn)
- + {
- + if(GET_CODE(tinsn)==INSN || GET_CODE(tinsn)==CALL_INSN)
- + {
- + add_dependence (insn,tinsn,0);
- + }
- + tinsn = NEXT_INSN(tinsn);
- + }
- + if(last_hard_reg_insn)
- + {
- + add_dependence (insn,last_hard_reg_insn,0);
- + }
- + first_insn_to_pivot = insn;
- + last_hard_reg_insn = insn;
- + }
- + #endif
- }
- else
- {
- ***************
- *** 1806,1811 ****
- --- 2126,2151 ----
- if (x == 0)
- return;
-
- + /* intel1 */
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + #ifdef NO_STACK_REG_REORDER
- + if (NO_STACK_REG_REORDER)
- + {
- + if (prev_stack_reg_insn!=NULL && insn!=prev_stack_reg_insn
- + && IS_STACK_MODE (GET_MODE (x)))
- + {
- + add_dependence (insn, prev_stack_reg_insn, REG_DEP_TMP);
- + }
- + if (IS_STACK_MODE (GET_MODE (x)))
- + {
- + prev_stack_reg_insn = insn;
- + }
- + }
- + #endif
- + #endif
- + #endif
- +
- code = GET_CODE (x);
-
- switch (code)
- ***************
- *** 1871,1876 ****
- --- 2211,2243 ----
- /* Function calls clobber all call_used regs. */
- add_dependence (insn, last_function_call, REG_DEP_ANTI);
- }
- + #ifdef SMALL_REGISTER_CLASSES
- + /* intel1
- + lifetime of hard registers must not be changed so this
- + insn becomes a pivot in the block.
- + */
- + if(reload_completed==0 && regno!=STACK_POINTER_REGNUM
- + && regno!=FRAME_POINTER_REGNUM)
- + {
- + rtx tinsn;
- +
- + tinsn = first_insn_to_pivot;
- + while(tinsn!=insn)
- + {
- + if(GET_CODE(tinsn)==INSN || GET_CODE(tinsn)==CALL_INSN)
- + {
- + add_dependence (insn,tinsn,0);
- + }
- + tinsn = NEXT_INSN(tinsn);
- + }
- + if(last_hard_reg_insn)
- + {
- + add_dependence (insn,last_hard_reg_insn,0);
- + }
- + first_insn_to_pivot = insn;
- + last_hard_reg_insn = insn;
- + }
- + #endif
- }
- else
- {
- ***************
- *** 2023,2028 ****
- --- 2390,2403 ----
- int maxreg = max_reg_num ();
- int i;
-
- + #ifdef SMALL_REGISTER_CLASSES
- + /* intel1 */
- + if (reload_completed==0 && last_hard_reg_insn!=NULL)
- + {
- + add_dependence (insn,last_hard_reg_insn,0);
- + }
- + #endif
- +
- if (code == SET || code == CLOBBER)
- sched_analyze_1 (x, insn);
- else if (code == PARALLEL)
- ***************
- *** 2170,2175 ****
- --- 2545,2571 ----
- register int luid = 0;
- rtx loop_notes = 0;
-
- + /* intel1 */
- + rtx pinsn;
- + #ifdef STACK_REGS
- + pinsn = NULL;
- + if (maintain_order && reload_completed==0)
- + { /* A block we don't want to change order but keep track of
- + register life information. */
- + for (insn = head; insn != tail; insn = NEXT_INSN (insn))
- + {
- + if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
- + {
- + if (pinsn)
- + {
- + add_dependence (insn, pinsn, REG_DEP_TMP);
- + }
- + pinsn = insn;
- + }
- + }
- + }
- + #endif
- +
- for (insn = head; ; insn = NEXT_INSN (insn))
- {
- INSN_LUID (insn) = luid++;
- ***************
- *** 2514,2519 ****
- --- 2910,2931 ----
- rtx note;
- int n_deaths = 0;
-
- + /* intel1 */
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + #ifdef STACK_REG_REORDER
- + /* For stack registers don't take lifetimes into account */
- + if (birthing_insn_p (PATTERN (prev)) && STACK_REG_REORDER && 0)
- + {
- + if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SET
- + && IS_STACK_MODE (GET_MODE (SET_DEST (PATTERN (prev)))))
- + {
- + return;
- + }
- + }
- + #endif
- + #endif
- + #endif
- /* ??? This code has no effect, because REG_DEAD notes are removed
- before we ever get here. */
- for (note = REG_NOTES (prev); note; note = XEXP (note, 1))
- ***************
- *** 2724,2730 ****
-
- if (dead_notes == 0)
- {
- ! #if 1
- abort ();
- #else
- link = rtx_alloc (EXPR_LIST);
- --- 3136,3143 ----
-
- if (dead_notes == 0)
- {
- ! /* Sorry for this hack */
- ! #if 0
- abort ();
- #else
- link = rtx_alloc (EXPR_LIST);
- ***************
- *** 3169,3178 ****
- --- 3582,3625 ----
- register struct sometimes *regs_sometimes_live;
- int sometimes_max;
-
- + /* intel1 */
- + #ifdef HAVE_cc0
- + rtx prev_to_cc0_setter;
- + #endif
- + #ifdef AGI
- + int possible_agi = 0;
- + #endif
- + #ifdef NO_STACK_REG_REORDER
- + rtx tinsn, tlink, tprev_link;
- + #endif /* NO_STACK_REG_REORDER */
- +
- if (file)
- fprintf (file, ";;\t -- basic block number %d from %d to %d --\n",
- b, INSN_UID (basic_block_head[b]), INSN_UID (basic_block_end[b]));
-
- + /* intel1 */
- + #ifdef NO_STACK_REG_REORDER
- + prev_stack_reg_insn = NULL;
- + #endif
- + #ifdef STACK_REGS
- + maintain_order = 0;
- + if (STACK_NON_STACK_INTERLEAVE || STACK_REG_REORDER)
- + {
- + rtx tinsn = head;
- + int found_stack_mode = 0;
- + while (tinsn && !found_stack_mode && tinsn != tail)
- + {
- + if (GET_CODE (tinsn) == INSN && GET_CODE (PATTERN (tinsn)) == SET
- + && IS_STACK_MODE (GET_MODE (SET_DEST (PATTERN (tinsn)))))
- + {
- + found_stack_mode = 1;
- + }
- + tinsn = next_nonnote_insn (tinsn);
- + }
- + maintain_order = !found_stack_mode;
- + }
- + #endif
- +
- i = max_reg_num ();
- reg_last_uses = (rtx *) alloca (i * sizeof (rtx));
- bzero ((char *) reg_last_uses, i * sizeof (rtx));
- ***************
- *** 3264,3269 ****
- --- 3711,3721 ----
-
- LOG_LINKS (sched_before_next_call) = 0;
-
- + #ifdef SMALL_REGISTER_CLASSES
- + /* intel1 */
- + first_insn_to_pivot = head;
- + last_hard_reg_insn = NULL;
- + #endif
- n_insns += sched_analyze (head, tail);
- if (n_insns == 0)
- {
- ***************
- *** 3280,3285 ****
- --- 3732,3823 ----
- /* TAIL is now the last of the insns to be rearranged.
- Put those insns into the READY vector. */
- insn = tail;
- + /* intel1 */
- + #ifdef HAVE_cc0
- + /* intel1 further if we have done compare elimination then the
- + insn before the compare should not be moved */
- + if (head!=tail
- + && GET_CODE (basic_block_end[b])==JUMP_INSN
- + && GET_CODE (PATTERN (basic_block_end[b]))!=PARALLEL
- + && GET_CODE (PATTERN (basic_block_end[b]))!=ADDR_VEC
- + && GET_CODE (XEXP (SET_SRC (PATTERN (basic_block_end[b])),0))==NE
- + && GET_CODE (PREV_INSN (basic_block_end[b]))==INSN
- + && GET_CODE (PATTERN (PREV_INSN (basic_block_end[b])))==SET
- + && SET_DEST (PATTERN (PREV_INSN (basic_block_end[b])))==cc0_rtx
- + && GET_CODE (SET_SRC (PATTERN (PREV_INSN (basic_block_end[b]))))==COMPARE
- + && XEXP (SET_SRC (PATTERN (PREV_INSN (basic_block_end[b]))),1)==const0_rtx)
- + {
- + prev_to_cc0_setter =
- + prev_nonnote_insn( PREV_INSN (basic_block_end[b]));
- + if (! (prev_to_cc0_setter && RTX_IS_RISC_P (prev_to_cc0_setter))
- + && prev_insts_in_block (b,PREV_INSN (basic_block_end[b]))
- + && (head != PREV_INSN (basic_block_end[b])) )
- + {
- + SCHED_GROUP_P (PREV_INSN (basic_block_end[b]))=1;
- + /* Also must remove the
- + prev_nonnote_insn(PREV_INSN(basic_block_end[b]) from the
- + dependency chain of both basic_block_end[b] and
- + PREV_INSN(basic_block_end[b]), to ensure that it doesn't
- + go through the ready list also */
- + if(prev_to_cc0_setter
- + && (GET_CODE (prev_to_cc0_setter)==INSN
- + || GET_CODE (prev_to_cc0_setter)==CALL_INSN )
- + && ! RTX_IS_RISC_P (prev_to_cc0_setter)) /* intel2 */
- + {
- + if (find_insn_list (prev_to_cc0_setter,
- + LOG_LINKS (PREV_INSN (basic_block_end[b]))))
- + remove_dependence (PREV_INSN (basic_block_end[b]),
- + prev_to_cc0_setter);
- + if (find_insn_list (prev_to_cc0_setter,
- + LOG_LINKS ( basic_block_end[b])))
- + remove_dependence (basic_block_end[b],
- + prev_to_cc0_setter);
- + }
- + }
- + else
- + SCHED_GROUP_P(PREV_INSN(basic_block_end[b]))=0;
- + }
- + else
- + if (head!=tail
- + && GET_CODE (basic_block_end[b])==JUMP_INSN
- + && GET_CODE (PATTERN (basic_block_end[b]))!=PARALLEL
- + && GET_CODE (PATTERN (basic_block_end[b]))!=ADDR_VEC
- + && GET_CODE (PREV_INSN (basic_block_end[b]))==INSN
- + && GET_CODE (PATTERN (PREV_INSN (basic_block_end[b])))==SET
- + && SET_DEST (PATTERN (PREV_INSN (basic_block_end[b])))==cc0_rtx
- + && GET_CODE (SET_SRC (PATTERN (PREV_INSN (basic_block_end[b]))))!=COMPARE)
- + {
- + prev_to_cc0_setter =
- + prev_nonnote_insn( PREV_INSN (basic_block_end[b]));
- + if (! (prev_to_cc0_setter && RTX_IS_RISC_P (prev_to_cc0_setter))
- + && prev_insts_in_block (b,PREV_INSN (basic_block_end[b]))
- + && (head != PREV_INSN (basic_block_end[b])) )
- + {
- + SCHED_GROUP_P (PREV_INSN (basic_block_end[b]))=1;
- + /* Also must remove the
- + prev_nonnote_insn(PREV_INSN(basic_block_end[b]) from the
- + dependency chain of both basic_block_end[b] and
- + PREV_INSN(basic_block_end[b]), to ensure that it doesn't
- + go through the ready list also */
- + if(prev_to_cc0_setter
- + && (GET_CODE (prev_to_cc0_setter) == INSN
- + || GET_CODE (prev_to_cc0_setter) == CALL_INSN )
- + && ! RTX_IS_RISC_P (prev_to_cc0_setter)) /* intel2 */
- + {
- + if (find_insn_list (prev_to_cc0_setter,
- + LOG_LINKS (PREV_INSN (basic_block_end[b]))))
- + remove_dependence (PREV_INSN (basic_block_end[b]),
- + prev_to_cc0_setter);
- + if (find_insn_list (prev_to_cc0_setter,
- + LOG_LINKS ( basic_block_end[b])))
- + remove_dependence (basic_block_end[b],
- + prev_to_cc0_setter);
- + }
- + }
- + else
- + SCHED_GROUP_P(PREV_INSN(basic_block_end[b]))=0;
- + }
- + #endif
-
- /* For all branches, calls, uses, and cc0 setters, force them to remain
- in order at the end of the block by adding dependencies and giving
- ***************
- *** 3697,3710 ****
- for (; insn; insn = NEXT_INSN (insn))
- {
- if (file)
- ! fprintf (file, ";; launching %d before %d with %d stalls at T-%d\n",
- ! INSN_UID (insn), INSN_UID (last), stalls, clock);
- ready[new_ready++] = insn;
- q_size -= 1;
- }
- insn_queue[NEXT_Q_AFTER (q_ptr, stalls)] = 0;
- break;
- }
-
- q_ptr = NEXT_Q_AFTER (q_ptr, stalls); clock += stalls;
- }
- --- 4235,4253 ----
- for (; insn; insn = NEXT_INSN (insn))
- {
- if (file)
- ! fprintf (file, ";; launching %d before %d with %d stalls at T-%d i_q[%d]\n",
- ! INSN_UID (insn), INSN_UID (last), stalls, clock, new_ready);
- ready[new_ready++] = insn;
- q_size -= 1;
- }
- insn_queue[NEXT_Q_AFTER (q_ptr, stalls)] = 0;
- break;
- }
- + /* intel1 */
- + #ifdef AGI
- + if (new_ready == 1)
- + possible_agi = 1;
- + #endif
-
- q_ptr = NEXT_Q_AFTER (q_ptr, stalls); clock += stalls;
- }
- ***************
- *** 3715,3721 ****
-
- if (file)
- {
- ! fprintf (file, ";; ready list at T-%d:", clock);
- for (i = 0; i < new_ready; i++)
- fprintf (file, " %d (%x)",
- INSN_UID (ready[i]), INSN_PRIORITY (ready[i]));
- --- 4258,4265 ----
-
- if (file)
- {
- ! fprintf (file, ";; ready list at T-%d (new_r %d n_r %d):",
- ! clock, new_ready, n_ready);
- for (i = 0; i < new_ready; i++)
- fprintf (file, " %d (%x)",
- INSN_UID (ready[i]), INSN_PRIORITY (ready[i]));
- ***************
- *** 3934,3939 ****
- --- 4478,4498 ----
- INSN_PRIORITY (insn) = DONE_PRIORITY;
- }
- }
- + #ifdef AGI
- + if (possible_agi && reload_completed && flag_swap_for_agi)
- + {
- + rtx next_to_last = NEXT_INSN (last);
- + if (try_eliminate_agi (last, file))
- + { /* last has been swapped downwards */
- + if (PREV_INSN (last) == tail)
- + { /* last has moved down to become tail */
- + tail = last;
- + }
- + last = next_to_last;
- + insn = last;
- + }
- + }
- + #endif
- }
- if (q_size != 0)
- abort ();
- ***************
- *** 3946,3951 ****
- --- 4505,4538 ----
- TAIL is the last of those insns. */
- head = insn;
-
- + /* intel1 */
- + #ifdef NO_STACK_REG_REORDER
- + if (NO_STACK_REG_REORDER)
- + { /* remove all the REG_DEP_TMP dependencies that were added */
- + for (tinsn = head; tinsn != NEXT_INSN (tail); tinsn = NEXT_INSN (tinsn))
- + {
- + tlink = LOG_LINKS (tinsn);
- + tprev_link = tlink;
- + while (tlink)
- + {
- + if (REG_NOTE_KIND (tlink) == REG_DEP_TMP)
- + {
- + if (tlink == LOG_LINKS (tinsn))
- + {
- + LOG_LINKS (tinsn) = XEXP (tlink, 1);
- + }
- + else
- + {
- + XEXP (tprev_link, 1) = XEXP (tlink, 1);
- + }
- + }
- + tprev_link = tlink;
- + tlink = XEXP (tlink, 1);
- + }
- + }
- + }
- + #endif /* NO_STACK_REG_REORDER */
- +
- /* NOTE_LIST is the end of a chain of notes previously found
- among the insns. Insert them at the beginning of the insns. */
- if (note_list != 0)
- ***************
- *** 4670,4680 ****
- --- 5257,5355 ----
- int b;
- rtx insn;
-
- + cur_dump_file = dump_file;
- /* Taking care of this degenerate case makes the rest of
- this code simpler. */
- if (n_basic_blocks == 0)
- return;
-
- + /* intel1 */
- + #ifdef STACK_REGS
- + if (STACK_NON_STACK_INTERLEAVE || STACK_REG_REORDER)
- + {
- + rtx tinsn = get_insns();
- + int found_stack_mode = 0;
- + while (tinsn && !found_stack_mode)
- + {
- + if (GET_CODE (tinsn) == INSN && GET_CODE (PATTERN (tinsn)) == SET
- + && IS_STACK_MODE (GET_MODE (SET_DEST (PATTERN (tinsn)))))
- + {
- + found_stack_mode = 1;
- + }
- + tinsn = next_nonnote_insn (tinsn);
- + }
- + if (!found_stack_mode) /* Nothing to do */
- + {
- + unused_insn_list = 0;
- + unused_expr_list = 0;
- + return;
- + }
- + }
- + #endif
- + /* intel1 - Remove all LOG_LINK information as the reload pass
- + may have invalidated some LOG_LINKs eg:
- + before reload:
- + (insn 21 20 24 (set (reg:SI 25)
- + (ashiftrt:SI (reg/v:SI 22)
- + (const_int 3))) 142 {ashrsi3} (nil)
- + (nil))
- +
- + (insn 24 21 28 (set (reg/v:SI 22)
- + (and:SI (reg/v:SI 22)
- + (const_int 7))) 102 {andsi3} (nil)
- + (nil))
- +
- + (insn 28 24 29 (set (reg:QI 27)
- + (and:QI (mem:QI (plus:SI (reg:SI 25)
- + (symbol_ref:SI ("buf"))))
- + (mem/s:QI (plus:SI (reg/v:SI 22)
- + (symbol_ref:SI ("rmask")))))) 104 {andqi3}
- + (insn_list 21 (insn_list 24 (nil)))
- + (nil))
- +
- + after reload:
- + (insn:HI 21 281 24 (set (reg:SI %edx)
- + (ashiftrt:SI (reg:SI %edx)
- + (const_int 3))) 142 {ashrsi3} (nil)
- + (nil))
- +
- +
- + (insn 24 21 284 (set (reg/v:SI %ebp)
- + (and:SI (reg/v:SI %ebp)
- + (const_int 7))) 102 {andsi3} (nil)
- + (nil))
- +
- + (insn 284 24 28 (set (reg:QI %cl)
- + (mem:QI (plus:SI (reg:SI %edx)
- + (symbol_ref:SI ("buf"))))) -1 (nil)
- + (nil))
- +
- + (insn:HI 28 284 285 (set (reg:QI %cl)
- + (and:QI (reg:QI %cl)
- + (mem/s:QI (plus:SI (reg/v:SI %ebp)
- + (symbol_ref:SI ("rmask")))))) 104 {andqi3}
- + (insn_list 21 (insn_list 24 (nil)))
- + (nil))
- +
- + Note that the LOG_LINKs of insn 28 is no longer valid - it does
- + not depend directly on insn 21 any longer. Leaving the LOG_LINKs
- + as they are may produce suboptimal, although valid, schedules.
- + */
- + if (reload_completed)
- + {
- + rtx tinsn = get_insns();
- + while (tinsn)
- + {
- + if (GET_CODE (tinsn) == INSN || GET_CODE (tinsn) == CALL_INSN
- + || GET_CODE (tinsn) == JUMP_INSN)
- + {
- + LOG_LINKS (tinsn) = NULL;
- + }
- + tinsn = next_nonnote_insn (tinsn);
- + }
- + }
- +
- +
- /* Create an insn here so that we can hang dependencies off of it later. */
- sched_before_next_call
- = gen_rtx (INSN, VOIDmode, 0, NULL_RTX, NULL_RTX,
- ***************
- *** 4815,4820 ****
- --- 5490,5497 ----
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- + /* intel1 */
- + SCHED_GROUP_P(insn) = 0;
- }
-
- continue;
- ***************
- *** 4837,4842 ****
- --- 5514,5521 ----
- PUT_CODE (insn, NOTE);
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- + /* intel1 */
- + SCHED_GROUP_P(insn) = 0;
- if (insn == basic_block_head[b])
- basic_block_head[b] = first;
- if (insn == basic_block_end[b])
- ***************
- *** 4882,4887 ****
- --- 5561,5568 ----
- notes++;
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- + /* intel1 */
- + SCHED_GROUP_P(insn) = 0;
- }
- /* If the line number is unchanged, LINE is redundant. */
- else if (line
- ***************
- *** 4965,4968 ****
- --- 5646,5931 ----
- }
- }
- }
- + /* intel1
- + return 1 if insn_b is part of the SCHED_GROUP of insn_a
- + */
- + static int
- + is_part_of_group (insn_a, insn_b)
- + rtx insn_a;
- + rtx insn_b;
- + {
- + rtx pn;
- +
- + pn = PREV_INSN(insn_a);
- + while(pn)
- + {
- + if(GET_CODE(pn)==INSN || GET_CODE(pn)==CALL_INSN ||
- + GET_CODE(pn)==JUMP_INSN)
- + {
- + if(pn==insn_b)
- + {
- + return(1);
- + }
- + if(!SCHED_GROUP_P(pn))
- + {
- + return(0);
- + }
- + }
- + pn = PREV_INSN(pn);
- + }
- + return(0);
- + }
- +
- + /* intel1 return 1 if there are insts in block b before insn */
- + static int prev_insts_in_block(b, insn)
- + int b;
- + rtx insn;
- + {
- + insn = PREV_INSN(insn);
- + while(insn && insn!=basic_block_head[b])
- + {
- + if(GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- + {
- + return(1);
- + }
- + insn = PREV_INSN(insn);
- + }
- + if(insn &&
- + insn==basic_block_head[b] && GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- + {
- + return(1);
- + }
- + return(0);
- + }
- +
- + #ifdef AGI
- + /* intel1
- + If insn updates a register by a constant and NEXT_INSN (insn) uses
- + that register as a base or index and this is the only dependence
- + between the two insns - then try to swap these two insns by replacing
- + register with (register + constant) in NEXT_INSN (insn).
- + */
- + int try_eliminate_agi (insn, file)
- + rtx insn;
- + FILE * file;
- + {
- + rtx next;
- + int success;
- +
- + next = NEXT_INSN (insn);
- + if (!try_swap (insn))
- + {
- + return (0);
- + }
- + /* Now swap insn with next. */
- + PREV_INSN (NEXT_INSN (next)) = insn;
- + NEXT_INSN (insn) = NEXT_INSN (next);
- + NEXT_INSN (next) = insn;
- + PREV_INSN (insn) = next;
- + success = 1;
- + if (file)
- + {
- + fprintf (file, ";; swapped %d with %d to eliminate agi, %d is last scheduled\n",
- + INSN_UID (insn), INSN_UID (next), INSN_UID (next));
- + }
- + while (success)
- + { /* Keep trying to swap insn downwards */
- + success = try_swap (insn);
- + if (success)
- + {
- + next = NEXT_INSN (insn);
- + if (file)
- + {
- + fprintf (file, ";; (swapped %d with %d to eliminate agi)\n",
- + INSN_UID (insn), INSN_UID (next));
- + }
- + NEXT_INSN (PREV_INSN (insn)) = next;
- + PREV_INSN (next) = PREV_INSN (insn);
- + PREV_INSN (NEXT_INSN (next)) = insn;
- + NEXT_INSN (insn) = NEXT_INSN (next);
- + NEXT_INSN (next) = insn;
- + PREV_INSN (insn) = next;
- + }
- + }
- + return (1);
- + }
- +
- + int try_swap (insn)
- + rtx insn;
- + {
- + rtx next, tmp, src, dest, next_src, next_dest, reg_to_update,
- + copy_dest, copy_src;
- + int offst_update, updates_by_const, regno_updated, length, i,
- + insn_code_number, save_code;
- + char * fmt, * storage;
- + next = NEXT_INSN (insn);
- + if (GET_CODE (insn) != INSN || next == NULL || GET_CODE (next) != INSN
- + || GET_CODE (PATTERN (insn)) != SET || GET_CODE (PATTERN (next)) != SET)
- + {
- + return (0);
- + }
- + src = SET_SRC (PATTERN (insn));
- + dest = SET_DEST (PATTERN (insn));
- + next_src = SET_SRC (PATTERN (next));
- + next_dest = SET_DEST (PATTERN (next));
- + if (next_dest == cc0_rtx)
- + {
- + return (0);
- + }
- + if (rtx_equal_p (dest, next_dest))
- + {
- + return (0);
- + }
- + if (GET_CODE (next_dest) == REG)
- + {
- + if (reg_overlap_mentioned_p (next_dest, PATTERN (insn)))
- + {
- + return (0);
- + }
- + }
- + /* See if insn updates some register by a constant ammount */
- + updates_by_const = 0;
- + if (GET_CODE (dest) == REG)
- + {
- + if ((GET_CODE (src) == PLUS || GET_CODE (src) == MINUS)
- + && rtx_equal_p (XEXP (src, 0), dest)
- + && GET_CODE (XEXP (src, 1)) == CONST_INT)
- + {
- + updates_by_const = 1;
- + offst_update
- + = XINT (XEXP (src, 1), 0) * (GET_CODE (src) == PLUS ? 1 : -1);
- + regno_updated = REGNO (dest);
- + reg_to_update = dest;
- + }
- + }
- + if (GET_CODE (dest) == MEM && push_operand (dest, GET_MODE (dest))
- + && (GET_CODE (src) == REG
- + || (GET_CODE (src) == MEM && !side_effects_p (XEXP (src, 0)))))
- + {
- + updates_by_const = 1;
- + offst_update = GET_MODE_SIZE (GET_MODE (dest));
- + if (GET_CODE (XEXP (dest, 0)) == PRE_DEC ||
- + GET_CODE (XEXP (dest, 0)) == POST_DEC)
- + {
- + offst_update *= -1;
- + }
- + regno_updated = STACK_POINTER_REGNUM;
- + reg_to_update = stack_pointer_rtx;
- + }
- + if (!updates_by_const)
- + {
- + return (0);
- + }
- + if (!reg_overlap_mentioned_p (reg_to_update, PATTERN (next)))
- + {
- + return (0);
- + }
- + if (GET_CODE (dest) == MEM)
- + {
- + if (GET_CODE (next_src) == MEM
- + && true_dependence (dest, next_src))
- + {
- + return (0);
- + }
- + else if (GET_CODE (next_src) != REG)
- + {
- + fmt = GET_RTX_FORMAT (GET_CODE (next_src));
- + length = GET_RTX_LENGTH (GET_CODE (next_src));
- + for (i=0; i<length; i++)
- + {
- + if (fmt[i] == 'e' && GET_CODE (XEXP (next_src, i)) == MEM)
- + {
- + if (true_dependence (dest, XEXP (next_src, i)))
- + {
- + return (0);
- + }
- + }
- + }
- + }
- + if (GET_CODE (next_dest) == MEM
- + && true_dependence (dest, next_dest))
- + {
- + return (0);
- + }
- + }
- + if (GET_CODE (src) == MEM)
- + {
- + if (GET_CODE (next_dest) == MEM
- + && true_dependence (src, next_dest))
- + {
- + return (0);
- + }
- + }
- + /* First check that regno_updated is not used in next with any
- + other mode */
- + init_undo_buf ();
- + subst_in_insn (next, PATTERN (next), reg_to_update, const0_rtx, 0, 0);
- + if (reg_overlap_mentioned_p (reg_to_update, PATTERN (next)))
- + {
- + loop_undo_all ();
- + return (0);
- + }
- + loop_undo_all ();
- + /* Now substitute reg_to_update with reg_to_update + offst_update. */
- + storage = (char *) oballoc (0);
- + /* Since may be sharing of rtl */
- + copy_dest = copy_rtx (next_dest);
- + copy_src = copy_rtx (next_src);
- + SET_SRC (PATTERN (next)) = copy_src;
- + SET_DEST (PATTERN (next)) = copy_dest;
- + init_undo_buf ();
- + subst_in_insn (next, PATTERN (next), reg_to_update,
- + gen_rtx (PLUS , GET_MODE (reg_to_update), reg_to_update,
- + gen_rtx (CONST_INT, 0, offst_update)), 0, 0);
- + #ifdef REWRITE_ADDRESS
- + if (GET_CODE (copy_dest) == MEM)
- + {
- + REWRITE_ADDRESS (copy_dest);
- + }
- + if (GET_CODE (copy_src) == MEM)
- + {
- + REWRITE_ADDRESS (copy_src);
- + }
- + else
- + {
- + fmt = GET_RTX_FORMAT (GET_CODE (copy_src));
- + length = GET_RTX_LENGTH (GET_CODE (copy_src));
- + for (i=0; i<length; i++)
- + {
- + if (fmt[i] == 'e' && GET_CODE (XEXP (copy_src, i)) == MEM)
- + {
- + REWRITE_ADDRESS (XEXP (copy_src, i));
- + }
- + }
- + }
- + #endif
- + if ((insn_code_number = recog (PATTERN (next), next, 0)) < 0)
- + {
- + loop_undo_all ();
- + SET_DEST (PATTERN (next)) = next_dest;
- + SET_SRC (PATTERN (next)) = next_src;
- + obfree (storage);
- + return (0);
- + }
- + else
- + {
- + #ifdef REGISTER_CONSTRAINTS
- + save_code = INSN_CODE (next);
- + INSN_CODE (next) = insn_code_number;
- + insn_extract (next);
- + if (!constrain_operands (insn_code_number, 1))
- + {
- + loop_undo_all ();
- + SET_DEST (PATTERN (next)) = next_dest;
- + SET_SRC (PATTERN (next)) = next_src;
- + INSN_CODE (next) = save_code;
- + obfree (storage);
- + return (0);
- + }
- + #endif
- + }
- + return (1);
- + }
- + #endif
- +
- #endif /* INSN_SCHEDULING */
- diff -rNci gcc-2.7.2/stmt.c gcc-2.7.2p/stmt.c
- *** gcc-2.7.2/stmt.c Tue Sep 12 23:01:54 1995
- --- gcc-2.7.2p/stmt.c Thu Jun 15 12:08:17 1995
- ***************
- *** 467,472 ****
- --- 467,482 ----
- static void emit_jump_if_reachable PROTO((rtx));
- static void emit_case_nodes PROTO((rtx, case_node_ptr, rtx, tree));
-
- + int bc_expand_exit_loop_if_false ();
- + void bc_expand_start_cond ();
- + void bc_expand_end_cond ();
- + void bc_expand_start_else ();
- + void bc_expand_end_bindings ();
- + void bc_expand_start_case ();
- + void bc_check_for_full_enumeration_handling ();
- + void bc_expand_end_case ();
- + void bc_expand_decl ();
- +
- extern rtx bc_allocate_local ();
- extern rtx bc_allocate_variable_array ();
-
- ***************
- *** 553,560 ****
- last_insn = get_last_insn ();
- if (!optimize
- && (GET_CODE (last_insn) == CODE_LABEL
- ! || (GET_CODE (last_insn) == NOTE
- ! && prev_real_insn (last_insn) == 0)))
- emit_insn (gen_nop ());
- }
- }
- --- 563,569 ----
- last_insn = get_last_insn ();
- if (!optimize
- && (GET_CODE (last_insn) == CODE_LABEL
- ! || prev_real_insn (last_insn) == 0))
- emit_insn (gen_nop ());
- }
- }
- ***************
- *** 1246,1252 ****
- f->before_jump
- = emit_insns_after (cleanup_insns, f->before_jump);
-
- ! f->cleanup_list_list = TREE_CHAIN (lists);
- }
-
- if (stack_level)
- --- 1255,1261 ----
- f->before_jump
- = emit_insns_after (cleanup_insns, f->before_jump);
-
- ! TREE_VALUE (lists) = 0;
- }
-
- if (stack_level)
- ***************
- *** 1508,1514 ****
- for (tail = inputs; tail; tail = TREE_CHAIN (tail))
- {
- int j;
- - int allows_reg = 0;
-
- /* If there's an erroneous arg, emit no insn,
- because the ASM_INPUT would get VOIDmode
- --- 1517,1522 ----
- ***************
- *** 1524,1588 ****
-
- /* Make sure constraint has neither `=' nor `+'. */
-
- ! for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
- ! switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
- {
- - case '+': case '=':
- error ("input operand constraint contains `%c'",
- TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]);
- return;
- -
- - case '?': case '!': case '*': case '%': case '&':
- - case 'V': case 'm': case 'o': case '<': case '>':
- - case 'E': case 'F': case 'G': case 'H': case 'X':
- - case 's': case 'i': case 'n':
- - case 'I': case 'J': case 'K': case 'L': case 'M':
- - case 'N': case 'O': case 'P': case ',':
- - #ifdef EXTRA_CONSTRAINT
- - case 'Q': case 'R': case 'S': case 'T': case 'U':
- - #endif
- - break;
- -
- - case '0': case '1': case '2': case '3': case '4':
- - case 'p': case 'g': case 'r':
- - default:
- - allows_reg = 1;
- - break;
- }
-
- - if (! allows_reg)
- - mark_addressable (TREE_VALUE (tail));
- -
- XVECEXP (body, 3, i) /* argvec */
- = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
- if (CONSTANT_P (XVECEXP (body, 3, i))
- && ! general_operand (XVECEXP (body, 3, i),
- TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)))))
- ! {
- ! if (allows_reg)
- ! XVECEXP (body, 3, i)
- ! = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- ! XVECEXP (body, 3, i));
- ! else
- ! XVECEXP (body, 3, i)
- ! = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- ! XVECEXP (body, 3, i));
- ! }
- !
- ! if (! allows_reg
- ! && (GET_CODE (XVECEXP (body, 3, i)) == REG
- ! || GET_CODE (XVECEXP (body, 3, i)) == SUBREG
- ! || GET_CODE (XVECEXP (body, 3, i)) == CONCAT))
- ! {
- ! tree type = TREE_TYPE (TREE_VALUE (tail));
- ! rtx memloc = assign_stack_temp (TYPE_MODE (type),
- ! int_size_in_bytes (type), 1);
- !
- ! MEM_IN_STRUCT_P (memloc) = AGGREGATE_TYPE_P (type);
- ! emit_move_insn (memloc, XVECEXP (body, 3, i));
- ! XVECEXP (body, 3, i) = memloc;
- ! }
- !
- XVECEXP (body, 4, i) /* constraints */
- = gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- TREE_STRING_POINTER (TREE_PURPOSE (tail)));
- --- 1532,1554 ----
-
- /* Make sure constraint has neither `=' nor `+'. */
-
- ! for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)); j++)
- ! if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '='
- ! || TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '+')
- {
- error ("input operand constraint contains `%c'",
- TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]);
- return;
- }
-
- XVECEXP (body, 3, i) /* argvec */
- = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
- if (CONSTANT_P (XVECEXP (body, 3, i))
- && ! general_operand (XVECEXP (body, 3, i),
- TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)))))
- ! XVECEXP (body, 3, i)
- ! = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- ! XVECEXP (body, 3, i));
- XVECEXP (body, 4, i) /* constraints */
- = gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- TREE_STRING_POINTER (TREE_PURPOSE (tail)));
- ***************
- *** 1885,1891 ****
- momentary = suspend_momentary ();
- t = make_node (RTL_EXPR);
- resume_momentary (momentary);
- - do_pending_stack_adjust ();
- start_sequence_for_rtl_expr (t);
- NO_DEFER_POP;
- expr_stmts_for_value++;
- --- 1851,1856 ----
- ***************
- *** 2757,2816 ****
- && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
- && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG)
- {
- ! int i, bitpos, xbitpos;
- int big_endian_correction = 0;
- int bytes = int_size_in_bytes (TREE_TYPE (retval_rhs));
- int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
- - int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)),BITS_PER_WORD);
- rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs);
- ! rtx result_reg, src, dst;
- rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
- enum machine_mode tmpmode, result_reg_mode;
-
- ! /* Structures whose size is not a multiple of a word are aligned
- ! to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
- ! machine, this means we must skip the empty high order bytes when
- ! calculating the bit offset. */
- ! if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
- ! big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
- ! * BITS_PER_UNIT));
- !
- ! /* Copy the structure BITSIZE bits at a time. */
- ! for (bitpos = 0, xbitpos = big_endian_correction;
- ! bitpos < bytes * BITS_PER_UNIT;
- ! bitpos += bitsize, xbitpos += bitsize)
- ! {
- ! /* We need a new destination pseudo each time xbitpos is
- ! on a word boundary and when xbitpos == big_endian_correction
- ! (the first time through). */
- ! if (xbitpos % BITS_PER_WORD == 0
- ! || xbitpos == big_endian_correction)
- {
- ! /* Generate an appropriate register. */
- ! dst = gen_reg_rtx (word_mode);
- ! result_pseudos[xbitpos / BITS_PER_WORD] = dst;
-
- ! /* Clobber the destination before we move anything into it. */
- ! emit_insn (gen_rtx (CLOBBER, VOIDmode, dst));
- }
- -
- - /* We need a new source operand each time bitpos is on a word
- - boundary. */
- - if (bitpos % BITS_PER_WORD == 0)
- - src = operand_subword_force (result_val,
- - bitpos / BITS_PER_WORD,
- - BLKmode);
- -
- - /* Use bitpos for the source extraction (left justified) and
- - xbitpos for the destination store (right justified). */
- - store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD, word_mode,
- - extract_bit_field (src, bitsize,
- - bitpos % BITS_PER_WORD, 1,
- - NULL_RTX, word_mode,
- - word_mode,
- - bitsize / BITS_PER_UNIT,
- - BITS_PER_WORD),
- - bitsize / BITS_PER_UNIT, BITS_PER_WORD);
- }
-
- /* Find the smallest integer mode large enough to hold the
- --- 2722,2772 ----
- && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
- && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG)
- {
- ! int i;
- int big_endian_correction = 0;
- int bytes = int_size_in_bytes (TREE_TYPE (retval_rhs));
- int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
- rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs);
- ! rtx result_reg;
- rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
- enum machine_mode tmpmode, result_reg_mode;
-
- ! /* Structures smaller than a word are aligned to the least significant
- ! byte (to the right). On a BYTES_BIG_ENDIAN machine, this means we
- ! must skip the empty high order bytes when calculating the bit
- ! offset. */
- ! if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD)
- ! big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT));
- !
- ! for (i = 0; i < n_regs; i++)
- ! {
- ! rtx reg = gen_reg_rtx (word_mode);
- ! rtx word = operand_subword_force (result_val, i, BLKmode);
- ! int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)),BITS_PER_WORD);
- ! int bitpos;
- !
- ! result_pseudos[i] = reg;
- !
- ! /* Clobber REG and move each partword into it. Ensure we don't
- ! go past the end of the structure. Note that the loop below
- ! works because we've already verified that padding and
- ! endianness are compatible. */
- ! emit_insn (gen_rtx (CLOBBER, VOIDmode, reg));
- !
- ! for (bitpos = 0;
- ! bitpos < BITS_PER_WORD && bytes > 0;
- ! bitpos += bitsize, bytes -= bitsize / BITS_PER_UNIT)
- {
- ! int xbitpos = bitpos + big_endian_correction;
-
- ! store_bit_field (reg, bitsize, xbitpos, word_mode,
- ! extract_bit_field (word, bitsize, bitpos, 1,
- ! NULL_RTX, word_mode,
- ! word_mode,
- ! bitsize / BITS_PER_UNIT,
- ! BITS_PER_WORD),
- ! bitsize / BITS_PER_UNIT, BITS_PER_WORD);
- }
- }
-
- /* Find the smallest integer mode large enough to hold the
- ***************
- *** 3310,3316 ****
- }
-
- /* Generate RTL for the automatic variable declaration DECL.
- ! (Other kinds of declarations are simply ignored if seen here.) */
-
- void
- expand_decl (decl)
- --- 3266,3287 ----
- }
-
- /* Generate RTL for the automatic variable declaration DECL.
- ! (Other kinds of declarations are simply ignored if seen here.)
- ! CLEANUP is an expression to be executed at exit from this binding contour;
- ! for example, in C++, it might call the destructor for this variable.
- !
- ! If CLEANUP contains any SAVE_EXPRs, then you must preevaluate them
- ! either before or after calling `expand_decl' but before compiling
- ! any subsequent expressions. This is because CLEANUP may be expanded
- ! more than once, on different branches of execution.
- ! For the same reason, CLEANUP may not contain a CALL_EXPR
- ! except as its topmost node--else `preexpand_calls' would get confused.
- !
- ! If CLEANUP is nonzero and DECL is zero, we record a cleanup
- ! that is not associated with any particular variable.
- !
- ! There is no special support here for C++ constructors.
- ! They should be handled by the proper code in DECL_INITIAL. */
-
- void
- expand_decl (decl)
- ***************
- *** 3683,3689 ****
- for example, in C++, it might call the destructor for this variable.
-
- If CLEANUP contains any SAVE_EXPRs, then you must preevaluate them
- ! either before or after calling `expand_decl_cleanup' but before compiling
- any subsequent expressions. This is because CLEANUP may be expanded
- more than once, on different branches of execution.
- For the same reason, CLEANUP may not contain a CALL_EXPR
- --- 3654,3660 ----
- for example, in C++, it might call the destructor for this variable.
-
- If CLEANUP contains any SAVE_EXPRs, then you must preevaluate them
- ! either before or after calling `expand_decl' but before compiling
- any subsequent expressions. This is because CLEANUP may be expanded
- more than once, on different branches of execution.
- For the same reason, CLEANUP may not contain a CALL_EXPR
- ***************
- *** 3726,3733 ****
- struct nesting *thisblock = block_stack;
- rtx x;
-
- ! expand_decl (decl);
- ! expand_decl_cleanup (decl, cleanup);
- x = DECL_RTL (decl);
-
- while (decl_elts)
- --- 3697,3703 ----
- struct nesting *thisblock = block_stack;
- rtx x;
-
- ! expand_decl (decl, cleanup);
- x = DECL_RTL (decl);
-
- while (decl_elts)
- diff -rNci gcc-2.7.2/stor-layout.c gcc-2.7.2p/stor-layout.c
- *** gcc-2.7.2/stor-layout.c Tue Oct 3 23:15:07 1995
- --- gcc-2.7.2p/stor-layout.c Thu Jun 15 12:08:47 1995
- ***************
- *** 81,96 ****
- return chain;
- }
-
- - void
- - put_pending_sizes (chain)
- - tree chain;
- - {
- - if (pending_sizes)
- - abort ();
- -
- - pending_sizes = chain;
- - }
- -
- /* Given a size SIZE that may not be a constant, return a SAVE_EXPR
- to serve as the actual size-expression for a type or decl. */
-
- --- 81,86 ----
- ***************
- *** 747,774 ****
- if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index)
- && TYPE_SIZE (element))
- {
- ! tree ub = TYPE_MAX_VALUE (index);
- ! tree lb = TYPE_MIN_VALUE (index);
- ! tree length;
- !
- ! /* If UB is max (lb - 1, x), remove the MAX_EXPR since the
- ! test for negative below covers it. */
- ! if (TREE_CODE (ub) == MAX_EXPR
- ! && TREE_CODE (TREE_OPERAND (ub, 0)) == MINUS_EXPR
- ! && integer_onep (TREE_OPERAND (TREE_OPERAND (ub, 0), 1))
- ! && operand_equal_p (TREE_OPERAND (TREE_OPERAND (ub, 0), 0),
- ! lb, 0))
- ! ub = TREE_OPERAND (ub, 1);
- ! else if (TREE_CODE (ub) == MAX_EXPR
- ! && TREE_CODE (TREE_OPERAND (ub, 1)) == MINUS_EXPR
- ! && integer_onep (TREE_OPERAND (TREE_OPERAND (ub, 1), 1))
- ! && operand_equal_p (TREE_OPERAND (TREE_OPERAND (ub, 1),
- ! 0),
- ! lb, 0))
- ! ub = TREE_OPERAND (ub, 0);
- !
- ! length = size_binop (PLUS_EXPR, size_one_node,
- ! size_binop (MINUS_EXPR, ub, lb));
-
- /* If neither bound is a constant and sizetype is signed, make
- sure the size is never negative. We should really do this
- --- 737,746 ----
- if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index)
- && TYPE_SIZE (element))
- {
- ! tree length
- ! = size_binop (PLUS_EXPR, size_one_node,
- ! size_binop (MINUS_EXPR, TYPE_MAX_VALUE (index),
- ! TYPE_MIN_VALUE (index)));
-
- /* If neither bound is a constant and sizetype is signed, make
- sure the size is never negative. We should really do this
- diff -rNci gcc-2.7.2/stupid.c gcc-2.7.2p/stupid.c
- *** gcc-2.7.2/stupid.c Sun Oct 29 12:45:22 1995
- --- gcc-2.7.2p/stupid.c Thu Jun 15 12:09:19 1995
- ***************
- *** 423,441 ****
-
- if (code == SET || code == CLOBBER)
- {
- ! if (SET_DEST (x) != 0
- ! && (GET_CODE (SET_DEST (x)) == REG
- ! || (GET_CODE (SET_DEST (x)) == SUBREG
- ! && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
- ! && (REGNO (SUBREG_REG (SET_DEST (x)))
- ! >= FIRST_PSEUDO_REGISTER))))
- {
- /* Register is being assigned. */
- ! /* If setting a SUBREG, we treat the entire reg as being set. */
- ! if (GET_CODE (SET_DEST (x)) == SUBREG)
- ! regno = REGNO (SUBREG_REG (SET_DEST (x)));
- ! else
- ! regno = REGNO (SET_DEST (x));
-
- /* For hard regs, update the where-live info. */
- if (regno < FIRST_PSEUDO_REGISTER)
- --- 423,432 ----
-
- if (code == SET || code == CLOBBER)
- {
- ! if (SET_DEST (x) != 0 && GET_CODE (SET_DEST (x)) == REG)
- {
- /* Register is being assigned. */
- ! regno = REGNO (SET_DEST (x));
-
- /* For hard regs, update the where-live info. */
- if (regno < FIRST_PSEUDO_REGISTER)
- diff -rNci gcc-2.7.2/toplev.c gcc-2.7.2p/toplev.c
- *** gcc-2.7.2/toplev.c Fri Oct 20 21:56:35 1995
- --- gcc-2.7.2p/toplev.c Tue Jan 23 09:25:32 1996
- ***************
- *** 205,211 ****
- --- 201,209 ----
- int combine_dump = 0;
- int sched_dump = 0;
- int local_reg_dump = 0;
- + int memory_simplify_dump = 0; /* intel2 */
- int global_reg_dump = 0;
- + int loop2_dump = 0; /* intel1 */
- int sched2_dump = 0;
- int jump2_opt_dump = 0;
- int dbr_sched_dump = 0;
- ***************
- *** 374,379 ****
- --- 372,413 ----
- /* Nonzero enables strength-reduction in loop.c. */
-
- int flag_strength_reduce = 0;
- + /* intel1 my optimization controllers */
- + int flag_opt_reg_use = 0;
- + int flag_all_mem_givs = 0;
- + int flag_reduce_index_givs = 0;
- + int flag_peep_spills = 0;
- + int flag_loop_after_global = 0;
- + int flag_jump_back = 0;
- + int flag_copy_prop = 0;
- + int flag_lift_stores = 0;
- + int flag_runtime_lift_stores = 0;
- + int flag_compare_elim = 0;
- + int flag_sign_extension_elim = 0;
- + int flag_sftwr_pipe = 0;
- + int flag_opt_jumps_out = 0;
- + int flag_replace_mem = 0;
- + int flag_replace_stack_mem = 0;
- + int flag_reg_reg_copy_opt = 0;
- + int flag_do_offload = 0;
- + int flag_opt_reg_stack = 0;
- + int flag_correct_cse_mistakes = 0;
- + int flag_push_load_into_loop = 0;
- + int flag_risc = 0;
- + int flag_risc_const = 0;
- + int flag_risc_mem_dest = 0; /* intel2 */
- + int flag_replace_reload_regs = 0;
- + int flag_recombine = 0;
- + int flag_swap_for_agi = 0;
- + int flag_no_omit_frame_pointer = 0;
- + int flag_no_risc = 0;
- + int flag_no_risc_const = 0;
- + int flag_no_risc_mem_dest = 0; /* intel2 */
- + int flag_no_recombine = 0;
- + int flag_schedule_stack_reg_insns = 0;
- + int flag_interleave_stack_non_stack = 0;
- + int flag_no_schedule_stack_reg_insns = 0;
- + int flag_no_interleave_stack_non_stack = 0;
-
- /* Nonzero enables loop unrolling in unroll.c. Only loops for which the
- number of iterations can be calculated at compile-time (UNROLL_COMPLETELY,
- ***************
- *** 567,573 ****
- {"verbose-asm", &flag_verbose_asm, 1},
- {"gnu-linker", &flag_gnu_linker, 1},
- {"pack-struct", &flag_pack_struct, 1},
- ! {"bytecode", &output_bytecode, 1}
- };
-
- /* Table of language-specific options. */
- --- 601,642 ----
- {"verbose-asm", &flag_verbose_asm, 1},
- {"gnu-linker", &flag_gnu_linker, 1},
- {"pack-struct", &flag_pack_struct, 1},
- ! {"bytecode", &output_bytecode, 1},
- ! /* intel1 */
- ! {"compare-elim", &flag_compare_elim, 1},
- ! {"sign-extension-elim", &flag_sign_extension_elim, 1},
- ! {"jump-back", &flag_jump_back, 1},
- ! {"loop-after-global", &flag_loop_after_global, 1},
- ! {"opt-reg-use", &flag_opt_reg_use, 1},
- ! {"all-mem-givs", &flag_all_mem_givs, 1},
- ! {"reduce-index-givs", &flag_reduce_index_givs, 1},
- ! {"peep-spills", &flag_peep_spills, 1},
- ! {"copy-prop", &flag_copy_prop, 1},
- ! {"lift-stores", &flag_lift_stores, 1},
- ! {"runtime-lift-stores", &flag_runtime_lift_stores, 1},
- ! {"do-offload", &flag_do_offload, 1},
- ! {"opt-reg-stack", &flag_opt_reg_stack, 1},
- ! {"correct-cse-mistakes", &flag_correct_cse_mistakes, 1},
- ! {"spl", &flag_sftwr_pipe, 1},
- ! {"opt-jumps-out", &flag_opt_jumps_out, 1},
- ! {"replace-mem", &flag_replace_mem, 1},
- ! {"replace-stack-mem", &flag_replace_stack_mem, 1},
- ! {"no-interleave-stack-non-stack", &flag_no_interleave_stack_non_stack, 1},
- ! {"interleave-stack-non-stack", &flag_interleave_stack_non_stack, 1},
- ! {"no-schedule-stack-reg-insns", &flag_no_schedule_stack_reg_insns, 1},
- ! {"schedule-stack-reg-insns", &flag_schedule_stack_reg_insns, 1},
- ! {"reg-reg-copy-opt", &flag_reg_reg_copy_opt, 1},
- ! {"push-load-into-loop", &flag_push_load_into_loop, 1},
- ! {"swap-for-agi", &flag_swap_for_agi, 1},
- ! {"no-recombine", &flag_no_recombine, 1},
- ! {"recombine", &flag_recombine, 1},
- ! {"no-risc", &flag_no_risc, 1},
- ! {"risc", &flag_risc, 1},
- ! {"no-risc-const", &flag_no_risc_const, 1},
- ! {"risc-const", &flag_risc_const, 1},
- ! {"replace-reload-regs", &flag_replace_reload_regs, 1},
- ! {"no-risc-mem-dest", &flag_no_risc_mem_dest, 1}, /* intel2 */
- ! {"risc-mem-dest", &flag_risc_mem_dest, 1}, /* intel2 */
- };
-
- /* Table of language-specific options. */
- ***************
- *** 756,761 ****
- --- 825,833 ----
- FILE *sched_dump_file;
- FILE *local_reg_dump_file;
- FILE *global_reg_dump_file;
- + FILE *memory_simplify_dump_file; /* intel2 */
- + /* intel1 */
- + FILE *loop2_dump_file;
- FILE *sched2_dump_file;
- FILE *jump2_opt_dump_file;
- FILE *dbr_sched_dump_file;
- ***************
- *** 775,780 ****
- --- 847,855 ----
- int sched_time;
- int local_alloc_time;
- int global_alloc_time;
- + int memory_simplify_time; /* intel2 */
- + /* intel1 */
- + int loop2_time;
- int sched2_time;
- int dbr_sched_time;
- int shorten_branch_time;
- ***************
- *** 926,931 ****
- --- 1001,1010 ----
- fflush (local_reg_dump_file);
- if (global_reg_dump_file)
- fflush (global_reg_dump_file);
- + if (memory_simplify_dump_file) /* intel2 */
- + fflush (memory_simplify_dump_file);
- + if (loop2_dump_file) /* intel1 */
- + fflush (loop2_dump_file);
- if (sched2_dump_file)
- fflush (sched2_dump_file);
- if (jump2_opt_dump_file)
- ***************
- *** 1052,1059 ****
- (*print_error_function) (file);
-
- if (input_file_stack && input_file_stack->next != 0
- ! && input_file_stack_tick != last_error_tick
- ! && file == input_filename)
- {
- fprintf (stderr, "In file included");
- for (p = input_file_stack->next; p; p = p->next)
- --- 1131,1137 ----
- (*print_error_function) (file);
-
- if (input_file_stack && input_file_stack->next != 0
- ! && input_file_stack_tick != last_error_tick)
- {
- fprintf (stderr, "In file included");
- for (p = input_file_stack->next; p; p = p->next)
- ***************
- *** 1085,1092 ****
- HOST_WIDE_INT v1 = va_arg(ap, HOST_WIDE_INT);
- HOST_WIDE_INT v2 = va_arg(ap, HOST_WIDE_INT);
- HOST_WIDE_INT v3 = va_arg(ap, HOST_WIDE_INT);
- ! HOST_WIDE_INT v4 = va_arg(ap, HOST_WIDE_INT);
- ! fprintf (stderr, s, v1, v2, v3, v4);
- }
- #endif
- }
- --- 1163,1169 ----
- HOST_WIDE_INT v1 = va_arg(ap, HOST_WIDE_INT);
- HOST_WIDE_INT v2 = va_arg(ap, HOST_WIDE_INT);
- HOST_WIDE_INT v3 = va_arg(ap, HOST_WIDE_INT);
- ! fprintf (stderr, s, v1, v2, v3);
- }
- #endif
- }
- ***************
- *** 1863,1883 ****
- }
-
- /* Strip off a legitimate source ending from the input string NAME of
- ! length LEN. Rather than having to know the names used by all of
- ! our front ends, we strip off an ending of a period followed by one,
- ! two, or three characters. */
-
- void
- strip_off_ending (name, len)
- char *name;
- int len;
- {
- ! if (len > 2 && name[len - 2] == '.')
- ! name[len - 2] = '\0';
- ! else if (len > 3 && name[len - 3] == '.')
- ! name[len - 3] = '\0';
- ! else if (len > 4 && name[len - 4] == '.')
- ! name[len - 4] = '\0';
- }
-
- /* Output a quoted string. */
- --- 1940,1978 ----
- }
-
- /* Strip off a legitimate source ending from the input string NAME of
- ! length LEN. */
-
- void
- strip_off_ending (name, len)
- char *name;
- int len;
- {
- ! if (len > 2 && ! strcmp (".c", name + len - 2))
- ! name[len - 2] = 0;
- ! else if (len > 2 && ! strcmp (".m", name + len - 2))
- ! name[len - 2] = 0;
- ! else if (len > 2 && ! strcmp (".i", name + len - 2))
- ! name[len - 2] = 0;
- ! else if (len > 3 && ! strcmp (".ii", name + len - 3))
- ! name[len - 3] = 0;
- ! else if (len > 3 && ! strcmp (".co", name + len - 3))
- ! name[len - 3] = 0;
- ! else if (len > 3 && ! strcmp (".cc", name + len - 3))
- ! name[len - 3] = 0;
- ! else if (len > 2 && ! strcmp (".C", name + len - 2))
- ! name[len - 2] = 0;
- ! else if (len > 4 && ! strcmp (".cxx", name + len - 4))
- ! name[len - 4] = 0;
- ! else if (len > 4 && ! strcmp (".cpp", name + len - 4))
- ! name[len - 4] = 0;
- ! else if (len > 2 && ! strcmp (".f", name + len - 2))
- ! name[len - 2] = 0;
- ! /* Ada will use extensions like .ada, .adb, and .ads, so just test
- ! for "ad". */
- ! else if (len > 4 && ! strncmp (".ad", name + len - 4, 3))
- ! name[len - 4] = 0;
- ! else if (len > 4 && ! strcmp (".atr", name + len - 4))
- ! name[len - 4] = 0;
- }
-
- /* Output a quoted string. */
- ***************
- *** 1984,1989 ****
- --- 2079,2087 ----
- sched_time = 0;
- local_alloc_time = 0;
- global_alloc_time = 0;
- + memory_simplify_time = 0; /* intel2 */
- + /* intel1 */
- + loop2_time = 0;
- sched2_time = 0;
- dbr_sched_time = 0;
- shorten_branch_time = 0;
- ***************
- *** 2080,2085 ****
- --- 2178,2194 ----
- if (global_reg_dump)
- global_reg_dump_file = open_dump_file (dump_base_name, ".greg");
-
- + /* intel1 */
- + /* If loop invariants after greg dump desired, open the output file. */
- + if (loop2_dump)
- + loop2_dump_file = open_dump_file(dump_base_name, ".l2" );
- +
- + /* intel2 - begin */
- + /* If memory_simplify dump desired, open the output file. */
- + if (memory_simplify_dump)
- + memory_simplify_dump_file=open_dump_file(dump_base_name, ".msim");
- + /* intel2 - end */
- +
- /* If 2nd scheduling dump desired, open the output file. */
- if (sched2_dump)
- sched2_dump_file = open_dump_file (dump_base_name, ".sched2");
- ***************
- *** 2492,2497 ****
- --- 2601,2612 ----
- if (global_reg_dump)
- fclose (global_reg_dump_file);
-
- + if (memory_simplify_dump)
- + fclose (memory_simplify_dump_file); /* intel2 */
- +
- + if (loop2_dump) /* intel1 */
- + fclose (loop2_dump_file);
- +
- if (sched2_dump)
- fclose (sched2_dump_file);
-
- ***************
- *** 2520,2547 ****
- {
- fprintf (stderr,"\n");
- print_time ("parse", parse_time);
- -
- if (!output_bytecode)
- ! {
- ! print_time ("integration", integration_time);
- ! print_time ("jump", jump_time);
- ! print_time ("cse", cse_time);
- ! print_time ("loop", loop_time);
- ! print_time ("cse2", cse2_time);
- ! print_time ("flow", flow_time);
- ! print_time ("combine", combine_time);
- ! print_time ("sched", sched_time);
- ! print_time ("local-alloc", local_alloc_time);
- ! print_time ("global-alloc", global_alloc_time);
- ! print_time ("sched2", sched2_time);
- ! print_time ("dbranch", dbr_sched_time);
- ! print_time ("shorten-branch", shorten_branch_time);
- ! print_time ("stack-reg", stack_reg_time);
- ! print_time ("final", final_time);
- ! print_time ("varconst", varconst_time);
- ! print_time ("symout", symout_time);
- ! print_time ("dump", dump_time);
- ! }
- }
- }
-
- --- 2635,2664 ----
- {
- fprintf (stderr,"\n");
- print_time ("parse", parse_time);
- if (!output_bytecode)
- ! {
- ! print_time ("integration", integration_time);
- ! print_time ("jump", jump_time);
- ! print_time ("cse", cse_time);
- ! print_time ("loop", loop_time);
- ! print_time ("cse2", cse2_time);
- ! print_time ("flow", flow_time);
- ! print_time ("combine", combine_time);
- ! print_time ("sched", sched_time);
- ! print_time ("local-alloc", local_alloc_time);
- ! print_time ("global-alloc", global_alloc_time);
- ! print_time ("memory-simplify", memory_simplify_time); /* intel2 */
- ! /* intel1 */
- ! print_time ("loop2", loop2_time);
- ! print_time ("sched2", sched2_time);
- ! print_time ("dbranch", dbr_sched_time);
- ! print_time ("shorten-branch", shorten_branch_time);
- ! print_time ("stack-reg", stack_reg_time);
- ! print_time ("final", final_time);
- ! print_time ("varconst", varconst_time);
- ! print_time ("symout", symout_time);
- ! print_time ("dump", dump_time);
- ! }
- }
- }
-
- ***************
- *** 2981,2987 ****
- and write some of the results to dump file. */
-
- TIMEVAR (flow_time, flow_analysis (insns, max_reg_num (),
- ! flow_dump_file));
- if (warn_uninitialized)
- {
- uninitialized_vars_warning (DECL_INITIAL (decl));
- --- 3098,3104 ----
- and write some of the results to dump file. */
-
- TIMEVAR (flow_time, flow_analysis (insns, max_reg_num (),
- ! flow_dump_file /* intel2: */, 1));
- if (warn_uninitialized)
- {
- uninitialized_vars_warning (DECL_INITIAL (decl));
- ***************
- *** 3015,3020 ****
- --- 3132,3162 ----
- fflush (combine_dump_file);
- });
-
- + /* intel1 */
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + if (optimize > 0 && flag_opt_reg_stack)
- + {
- + if(stack_reg_dump)
- + {
- + TIMEVAR (dump_time,
- + {
- + fprintf (stack_reg_dump_file, "\n;; Function %s\n\n",
- + IDENTIFIER_POINTER (DECL_NAME (decl)));
- + });
- + }
- + opt_reg_stack();
- + if(stack_reg_dump)
- + {
- + TIMEVAR (dump_time,
- + {
- + print_rtl (stack_reg_dump_file, insns);
- + fflush (stack_reg_dump_file);
- + });
- + }
- + }
- + #endif
- + #endif
- /* Print function header into sched dump now
- because doing the sched analysis makes some of the dump. */
-
- ***************
- *** 3082,3087 ****
- --- 3224,3235 ----
- failure = reload (insns, 0, global_reg_dump_file);
- });
-
- + /* intel1 */
- + if(optimize > 0 && flag_reg_reg_copy_opt)
- + {
- + reg_to_reg_copy_opt(insns, global_reg_dump_file);
- + }
- +
- if (global_reg_dump)
- TIMEVAR (dump_time,
- {
- ***************
- *** 3095,3100 ****
- --- 3243,3312 ----
-
- reload_completed = 1;
-
- + #ifdef STACK_REGS
- + /* intel1 */
- + if (optimize > 0 && flag_opt_reg_stack)
- + {
- + TIMEVAR (stack_reg_time, float_to_int_cmp (insns, 0));
- + }
- + #endif
- +
- + /* intel1 */
- + if (loop2_dump)
- + TIMEVAR (dump_time,
- + {
- + fprintf (loop2_dump_file, "\n;; Function %s\n\n",
- + IDENTIFIER_POINTER (DECL_NAME (decl)));
- + });
- +
- + if(optimize>0 && flag_loop_after_global)
- + {
- + TIMEVAR (loop2_time,
- + {
- + /* intel2 - begin */
- + if (flag_replace_reload_regs)
- + replace_reload_registers (get_insns(),
- + loop2_dump ? loop2_dump_file : 0);
- + /* intel2 - end */
- + loop_after_global(get_insns(),loop2_dump ? loop2_dump_file : 0);
- + });
- + }
- + if (optimize>0 && flag_peep_spills)
- + {
- + TIMEVAR (loop2_time,
- + {
- + peep_spills(get_insns(),loop2_dump ? loop2_dump_file : 0);
- + });
- + }
- +
- + /* Dump rtl code after loop2 opt, if we are doing that. */
- +
- + if (loop2_dump && flag_loop_after_global)
- + TIMEVAR (dump_time,
- + {
- + print_rtl (loop2_dump_file, insns);
- + fflush (loop2_dump_file);
- + });
- +
- + /* intel2 - begin */
- + if (optimize>0 && flag_risc)
- + {
- + if (memory_simplify_dump)
- + TIMEVAR (dump_time,
- + fprintf (memory_simplify_dump_file, "\n;; Function %s\n\n",
- + IDENTIFIER_POINTER (DECL_NAME (decl))));
- +
- + TIMEVAR (memory_simplify_time,
- + memory_simplify (memory_simplify_dump ? memory_simplify_dump_file : 0,
- + insns));
- + if (memory_simplify_dump)
- + TIMEVAR (dump_time,
- + {
- + print_rtl (memory_simplify_dump_file, insns);
- + fflush (memory_simplify_dump_file);
- + });
- + }
- + /* intel2 - end */
- /* On some machines, the prologue and epilogue code, or parts thereof,
- can be represented as RTL. Doing so lets us schedule insns between
- it and the rest of the code and also allows delayed branch
- ***************
- *** 3126,3131 ****
- --- 3338,3350 ----
- });
- }
-
- + /* intel2 - begin */
- + /* Combine those riscified insns that were not used for scheduling */
- + if (flag_risc && flag_recombine)
- + combine_unscheded (get_insns (),max_reg_num ());
- + /* intel2 - end */
- +
- +
- #ifdef LEAF_REGISTERS
- leaf_function = 0;
- if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
- ***************
- *** 3185,3190 ****
- --- 3404,3414 ----
- });
-
- #ifdef STACK_REGS
- + /* intel1 */
- + if (optimize > 0 && flag_opt_reg_stack)
- + {
- + TIMEVAR (stack_reg_time, float_to_int_cmp (insns));
- + }
- TIMEVAR (stack_reg_time, reg_to_stack (insns, stack_reg_dump_file));
- if (stack_reg_dump)
- {
- ***************
- *** 3196,3201 ****
- --- 3420,3432 ----
- fflush (stack_reg_dump_file);
- });
- }
- + /* intel1 spl */
- + #ifdef STORE_NOT_SET_CC0
- + if(flag_sftwr_pipe)
- + {
- + do_spl(insns);
- + }
- + #endif
- #endif
-
- /* Now turn the rtl into assembler code. */
- ***************
- *** 3267,3275 ****
-
- reload_completed = 0;
-
- - /* Clear out the insn_length contents now that they are no longer valid. */
- - init_insn_lengths ();
- -
- /* Clear out the real_constant_chain before some of the rtx's
- it runs through become garbage. */
-
- --- 3498,3503 ----
- ***************
- *** 3451,3460 ****
- --- 3679,3690 ----
- dbr_sched_dump = 1;
- flow_dump = 1;
- global_reg_dump = 1;
- + memory_simplify_dump = 1; /* intel2 */
- jump_opt_dump = 1;
- jump2_opt_dump = 1;
- local_reg_dump = 1;
- loop_dump = 1;
- + loop2_dump = 1; /* intel1 */
- rtl_dump = 1;
- cse_dump = 1, cse2_dump = 1;
- sched_dump = 1;
- ***************
- *** 3476,3481 ****
- --- 3706,3716 ----
- case 'g':
- global_reg_dump = 1;
- break;
- + /* intel2 - begin */
- + case 'b':
- + memory_simplify_dump = 1;
- + break;
- + /* intel2 - end */
- case 'j':
- jump_opt_dump = 1;
- break;
- ***************
- *** 3488,3493 ****
- --- 3723,3732 ----
- case 'L':
- loop_dump = 1;
- break;
- + /* intel1 */
- + case 'A':
- + loop2_dump = 1;
- + break;
- case 'm':
- flag_print_mem = 1;
- break;
- ***************
- *** 3791,3798 ****
- use_gnu_debug_info_extensions = DEFAULT_GDB_EXTENSIONS;
- #endif
- if (write_symbols == NO_DEBUG)
- ! warning ("`-%s' not supported by this configuration of GCC",
- ! str);
- else if (level == 0)
- write_symbols = NO_DEBUG;
- else
- --- 4030,4036 ----
- use_gnu_debug_info_extensions = DEFAULT_GDB_EXTENSIONS;
- #endif
- if (write_symbols == NO_DEBUG)
- ! warning ("`-%s' option not supported on this version of GCC", str);
- else if (level == 0)
- write_symbols = NO_DEBUG;
- else
- ***************
- *** 3827,3833 ****
- {
- #ifndef TARGET_SUPPORTS_BYTECODE
- /* Just die with a fatal error if not supported */
- ! fatal ("-fbytecode not supporter for this target");
- #else
- bc_initialize ();
- #endif
- --- 4065,4071 ----
- {
- #ifndef TARGET_SUPPORTS_BYTECODE
- /* Just die with a fatal error if not supported */
- ! fatal ("-fbytecode not supported for this target");
- #else
- bc_initialize ();
- #endif
- ***************
- *** 3851,3857 ****
- if (write_symbols == DWARF_DEBUG
- && strcmp (language_string, "GNU C++") == 0)
- {
- ! warning ("-g option not supported for C++ on systems using the DWARF debugging format");
- write_symbols = NO_DEBUG;
- }
- #endif /* defined(DWARF_DEBUGGING_INFO) */
- --- 4089,4095 ----
- if (write_symbols == DWARF_DEBUG
- && strcmp (language_string, "GNU C++") == 0)
- {
- ! warning ("-g option not supported for C++ on SVR4 systems");
- write_symbols = NO_DEBUG;
- }
- #endif /* defined(DWARF_DEBUGGING_INFO) */
- ***************
- *** 3893,3898 ****
- --- 4131,4139 ----
- #ifdef TARGET_VERSION
- TARGET_VERSION;
- #endif
- + #ifdef SUB_TARGET_VERSION
- + SUB_TARGET_VERSION;
- + #endif
- #ifdef __GNUC__
- #ifndef __VERSION__
- #define __VERSION__ "[unknown]"
- ***************
- *** 3910,3915 ****
- --- 4151,4159 ----
- #if !defined(OS2) && !defined(VMS) && !defined(_WIN32)
- if (flag_print_mem)
- {
- + #ifdef __alpha
- + char *sbrk ();
- + #endif
- char *lim = (char *) sbrk (0);
-
- fprintf (stderr, "Data size %d.\n",
- diff -rNci gcc-2.7.2/tree.c gcc-2.7.2p/tree.c
- *** gcc-2.7.2/tree.c Mon Oct 2 01:26:56 1995
- --- gcc-2.7.2p/tree.c Thu Jun 15 12:10:23 1995
- ***************
- *** 2058,2070 ****
- case BIT_FIELD_REF:
- return staticp (TREE_OPERAND (arg, 0));
-
- - #if 0
- - /* This case is technically correct, but results in setting
- - TREE_CONSTANT on ADDR_EXPRs that cannot be evaluated at
- - compile time. */
- case INDIRECT_REF:
- return TREE_CONSTANT (TREE_OPERAND (arg, 0));
- - #endif
-
- case ARRAY_REF:
- if (TREE_CODE (TYPE_SIZE (TREE_TYPE (arg))) == INTEGER_CST
- --- 2058,2065 ----
- ***************
- *** 2115,2121 ****
- literal node. */
-
- if (TREE_CONSTANT (t) || (TREE_READONLY (t) && ! TREE_SIDE_EFFECTS (t))
- ! || TREE_CODE (t) == SAVE_EXPR || TREE_CODE (t) == ERROR_MARK)
- return t;
-
- /* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
- --- 2110,2116 ----
- literal node. */
-
- if (TREE_CONSTANT (t) || (TREE_READONLY (t) && ! TREE_SIDE_EFFECTS (t))
- ! || TREE_CODE (t) == SAVE_EXPR)
- return t;
-
- /* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
- ***************
- *** 3598,3604 ****
- handled above. If this is a language-specific tree code, we can't
- trust what might be in the operand, so say we don't know
- the situation. */
- ! if ((int) code1
- >= sizeof standard_tree_code_type / sizeof standard_tree_code_type[0])
- return -1;
-
- --- 3593,3599 ----
- handled above. If this is a language-specific tree code, we can't
- trust what might be in the operand, so say we don't know
- the situation. */
- ! if (code1
- >= sizeof standard_tree_code_type / sizeof standard_tree_code_type[0])
- return -1;
-
- diff -rNci gcc-2.7.2/tree.h gcc-2.7.2p/tree.h
- *** gcc-2.7.2/tree.h Mon Sep 25 21:49:40 1995
- --- gcc-2.7.2p/tree.h Thu Jun 15 12:10:49 1995
- ***************
- *** 1289,1295 ****
- extern tree size_int PROTO((unsigned HOST_WIDE_INT));
- extern tree round_up PROTO((tree, int));
- extern tree get_pending_sizes PROTO((void));
- - extern void put_pending_sizes PROTO((tree));
-
- /* Type for sizes of data-type. */
-
- --- 1289,1294 ----
- ***************
- *** 1298,1304 ****
- /* If nonzero, an upper limit on alignment of structure fields, in bits. */
- extern int maximum_field_alignment;
-
- ! /* If non-zero, the alignment of a bitstring or (power-)set value, in bits. */
- extern int set_alignment;
-
- /* Concatenate two lists (chains of TREE_LIST nodes) X and Y
- --- 1297,1303 ----
- /* If nonzero, an upper limit on alignment of structure fields, in bits. */
- extern int maximum_field_alignment;
-
- ! /* If non-zero, the alignment of a bitsting or (power-)set value, in bits. */
- extern int set_alignment;
-
- /* Concatenate two lists (chains of TREE_LIST nodes) X and Y
- diff -rNci gcc-2.7.2/unroll.c gcc-2.7.2p/unroll.c
- *** gcc-2.7.2/unroll.c Sat Aug 19 21:33:26 1995
- --- gcc-2.7.2p/unroll.c Tue Jan 23 09:25:32 1996
- ***************
- *** 156,161 ****
- --- 156,164 ----
- #include <stdio.h>
- #include "loop.h"
-
- + /* intel1 */
- + extern FILE *loop_dump_stream;
- +
- /* This controls which loops are unrolled, and by how much we unroll
- them. */
-
- ***************
- *** 853,871 ****
- for (i = 0; i < unroll_number; i++)
- labels[i] = gen_label_rtx ();
-
- - /* Check for the case where the initial value is greater than or equal
- - to the final value. In that case, we want to execute exactly
- - one loop iteration. The code below will fail for this case. */
- -
- - emit_cmp_insn (initial_value, final_value, neg_inc ? LE : GE,
- - NULL_RTX, mode, 0, 0);
- - if (neg_inc)
- - emit_jump_insn (gen_ble (labels[1]));
- - else
- - emit_jump_insn (gen_bge (labels[1]));
- - JUMP_LABEL (get_last_insn ()) = labels[1];
- - LABEL_NUSES (labels[1])++;
- -
- /* Assuming the unroll_number is 4, and the increment is 2, then
- for a negative increment: for a positive increment:
- diff = 0,1 precond 0 diff = 0,7 precond 0
- --- 856,861 ----
- ***************
- *** 882,909 ****
- for (i = 0; i < unroll_number - 1; i++)
- {
- int cmp_const;
- - enum rtx_code cmp_code;
-
- /* For negative increments, must invert the constant compared
- against, except when comparing against zero. */
- if (i == 0)
- ! {
- ! cmp_const = 0;
- ! cmp_code = EQ;
- ! }
- else if (neg_inc)
- ! {
- ! cmp_const = unroll_number - i;
- ! cmp_code = GE;
- ! }
- else
- ! {
- ! cmp_const = i;
- ! cmp_code = LE;
- ! }
-
- emit_cmp_insn (diff, GEN_INT (abs_inc * cmp_const),
- ! cmp_code, NULL_RTX, mode, 0, 0);
-
- if (i == 0)
- emit_jump_insn (gen_beq (labels[i]));
- --- 872,889 ----
- for (i = 0; i < unroll_number - 1; i++)
- {
- int cmp_const;
-
- /* For negative increments, must invert the constant compared
- against, except when comparing against zero. */
- if (i == 0)
- ! cmp_const = 0;
- else if (neg_inc)
- ! cmp_const = unroll_number - i;
- else
- ! cmp_const = i;
-
- emit_cmp_insn (diff, GEN_INT (abs_inc * cmp_const),
- ! EQ, NULL_RTX, mode, 0, 0);
-
- if (i == 0)
- emit_jump_insn (gen_beq (labels[i]));
- ***************
- *** 927,946 ****
- if (abs_inc != 1)
- {
- int cmp_const;
- - enum rtx_code cmp_code;
-
- if (neg_inc)
- ! {
- ! cmp_const = abs_inc - 1;
- ! cmp_code = LE;
- ! }
- else
- ! {
- ! cmp_const = abs_inc * (unroll_number - 1) + 1;
- ! cmp_code = GE;
- ! }
-
- ! emit_cmp_insn (diff, GEN_INT (cmp_const), cmp_code, NULL_RTX,
- mode, 0, 0);
-
- if (neg_inc)
- --- 907,919 ----
- if (abs_inc != 1)
- {
- int cmp_const;
-
- if (neg_inc)
- ! cmp_const = abs_inc - 1;
- else
- ! cmp_const = abs_inc * (unroll_number - 1) + 1;
-
- ! emit_cmp_insn (diff, GEN_INT (cmp_const), EQ, NULL_RTX,
- mode, 0, 0);
-
- if (neg_inc)
- ***************
- *** 1412,1424 ****
- one of the LO_SUM rtx. */
- if (GET_CODE (increment) == LO_SUM)
- increment = XEXP (increment, 1);
- ! else if (GET_CODE (increment) == IOR
- ! || GET_CODE (increment) == ASHIFT)
- {
- ! /* The rs6000 port loads some constants with IOR.
- ! The alpha port loads some constants with ASHIFT. */
- rtx second_part = XEXP (increment, 1);
- - enum rtx_code code = GET_CODE (increment);
-
- src_insn = PREV_INSN (src_insn);
- increment = SET_SRC (PATTERN (src_insn));
- --- 1385,1394 ----
- one of the LO_SUM rtx. */
- if (GET_CODE (increment) == LO_SUM)
- increment = XEXP (increment, 1);
- ! else if (GET_CODE (increment) == IOR)
- {
- ! /* The rs6000 port loads some constants with IOR. */
- rtx second_part = XEXP (increment, 1);
-
- src_insn = PREV_INSN (src_insn);
- increment = SET_SRC (PATTERN (src_insn));
- ***************
- *** 1429,1438 ****
- || GET_CODE (increment) != CONST_INT)
- abort ();
-
- ! if (code == IOR)
- ! increment = GEN_INT (INTVAL (increment) | INTVAL (second_part));
- ! else
- ! increment = GEN_INT (INTVAL (increment) << INTVAL (second_part));
- }
-
- if (GET_CODE (increment) != CONST_INT)
- --- 1399,1405 ----
- || GET_CODE (increment) != CONST_INT)
- abort ();
-
- ! increment = GEN_INT (INTVAL (increment) | INTVAL (second_part));
- }
-
- if (GET_CODE (increment) != CONST_INT)
- ***************
- *** 1770,1775 ****
- --- 1737,1778 ----
- else
- {
- pattern = copy_rtx_and_substitute (pattern, map);
- + /* intel1 since a DEST_ADDR giv may be only a part of an address
- + then just substituting reg+const for reg may result in an
- + invalid insn - we check for that and try to make it good */
- + #if REDUCE_INDEX || SAVE_ON_REGS
- + if(GET_CODE(PATTERN(insn))==SET)
- + {
- + int dummy;
- + rtx try_to_make_good(); /* see loop.c */
- + if(recog(pattern,insn,&dummy)==-1)
- + {
- + try_to_make_good(SET_SRC(pattern));
- + try_to_make_good(SET_DEST(pattern));
- + if(recog(pattern,insn,&dummy)==-1)
- + {
- + fprintf(stderr,"bad pattern in insn not better:\n");
- + debug_rtx(insn);
- + abort();
- + }
- + }
- + }
- + #endif
- + /* intel1 Don't want to be reusing STACK_MODE registers
- + since that inhibits scheduling opportunities */
- + #ifdef STACK_REGS
- + #ifdef IS_STACK_MODE
- + #ifdef ONLY_STACK_REG_REORDER
- + if (GET_CODE (pattern) == SET && GET_CODE (SET_DEST (pattern)) == REG
- + && IS_STACK_MODE (GET_MODE (SET_DEST (pattern))))
- + {
- + tem = gen_reg_rtx (GET_MODE (SET_DEST (pattern)));
- + map->reg_map[REGNO (SET_DEST (PATTERN (insn)))] = tem;
- + SET_DEST (pattern) = tem;
- + }
- + #endif
- + #endif
- + #endif
- copy = emit_insn (pattern);
- }
- REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
- ***************
- *** 2393,2405 ****
- it is unsafe to split the biv since it may not have the proper
- value on loop exit. */
-
- ! /* loop_number_exit_count is non-zero if the loop has an exit other than
- a fall through at the end. */
-
- biv_splittable = 1;
- biv_final_value = 0;
- if (unroll_type != UNROLL_COMPLETELY
- ! && (loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]
- || unroll_type == UNROLL_NAIVE)
- && (uid_luid[regno_last_uid[bl->regno]] >= INSN_LUID (loop_end)
- || ! bl->init_insn
- --- 2396,2408 ----
- it is unsafe to split the biv since it may not have the proper
- value on loop exit. */
-
- ! /* loop_number_exit_labels is non-zero if the loop has an exit other than
- a fall through at the end. */
-
- biv_splittable = 1;
- biv_final_value = 0;
- if (unroll_type != UNROLL_COMPLETELY
- ! && (loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]]
- || unroll_type == UNROLL_NAIVE)
- && (uid_luid[regno_last_uid[bl->regno]] >= INSN_LUID (loop_end)
- || ! bl->init_insn
- ***************
- *** 2433,2445 ****
- {
- /* If the initial value of the biv is itself (i.e. it is too
- complicated for strength_reduce to compute), or is a hard
- ! register, or it isn't invariant, then we must create a new
- ! pseudo reg to hold the initial value of the biv. */
-
- if (GET_CODE (bl->initial_value) == REG
- && (REGNO (bl->initial_value) == bl->regno
- ! || REGNO (bl->initial_value) < FIRST_PSEUDO_REGISTER
- ! || ! invariant_p (bl->initial_value)))
- {
- rtx tem = gen_reg_rtx (bl->biv->mode);
-
- --- 2436,2447 ----
- {
- /* If the initial value of the biv is itself (i.e. it is too
- complicated for strength_reduce to compute), or is a hard
- ! register, then we must create a new pseudo reg to hold the
- ! initial value of the biv. */
-
- if (GET_CODE (bl->initial_value) == REG
- && (REGNO (bl->initial_value) == bl->regno
- ! || REGNO (bl->initial_value) < FIRST_PSEUDO_REGISTER))
- {
- rtx tem = gen_reg_rtx (bl->biv->mode);
-
- ***************
- *** 2487,2493 ****
- loop to ensure that it will always be executed no matter
- how the loop exits. Otherwise emit the insn after the loop,
- since this is slightly more efficient. */
- ! if (! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]])
- emit_insn_before (gen_move_insn (bl->biv->src_reg,
- biv_final_value),
- end_insert_before);
- --- 2489,2495 ----
- loop to ensure that it will always be executed no matter
- how the loop exits. Otherwise emit the insn after the loop,
- since this is slightly more efficient. */
- ! if (! loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]])
- emit_insn_before (gen_move_insn (bl->biv->src_reg,
- biv_final_value),
- end_insert_before);
- ***************
- *** 2610,2616 ****
-
- final_value = 0;
- if (unroll_type != UNROLL_COMPLETELY
- ! && (loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]
- || unroll_type == UNROLL_NAIVE)
- && v->giv_type != DEST_ADDR
- && ((regno_first_uid[REGNO (v->dest_reg)] != INSN_UID (v->insn)
- --- 2612,2618 ----
-
- final_value = 0;
- if (unroll_type != UNROLL_COMPLETELY
- ! && (loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]]
- || unroll_type == UNROLL_NAIVE)
- && v->giv_type != DEST_ADDR
- && ((regno_first_uid[REGNO (v->dest_reg)] != INSN_UID (v->insn)
- ***************
- *** 2950,2975 ****
- rtx insn, label;
- enum rtx_code code;
- int jump_count = 0;
- - int label_count = 0;
- - int this_loop_num = uid_loop_num[INSN_UID (loop_start)];
- -
- - /* In addition to checking all exits of this loop, we must also check
- - all exits of inner nested loops that would exit this loop. We don't
- - have any way to identify those, so we just give up if there are any
- - such inner loop exits. */
- -
- - for (label = loop_number_exit_labels[this_loop_num]; label;
- - label = LABEL_NEXTREF (label))
- - label_count++;
- -
- - if (label_count != loop_number_exit_count[this_loop_num])
- - return 0;
-
- /* HACK: Must also search the loop fall through exit, create a label_ref
- here which points to the loop_end, and append the loop_number_exit_labels
- list to it. */
- label = gen_rtx (LABEL_REF, VOIDmode, loop_end);
- ! LABEL_NEXTREF (label) = loop_number_exit_labels[this_loop_num];
-
- for ( ; label; label = LABEL_NEXTREF (label))
- {
- --- 2952,2964 ----
- rtx insn, label;
- enum rtx_code code;
- int jump_count = 0;
-
- /* HACK: Must also search the loop fall through exit, create a label_ref
- here which points to the loop_end, and append the loop_number_exit_labels
- list to it. */
- label = gen_rtx (LABEL_REF, VOIDmode, loop_end);
- ! LABEL_NEXTREF (label)
- ! = loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]];
-
- for ( ; label; label = LABEL_NEXTREF (label))
- {
- ***************
- *** 3048,3054 ****
- value of the biv must be invariant. */
-
- if (loop_n_iterations != 0
- ! && ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]
- && invariant_p (bl->initial_value))
- {
- increment = biv_total_increment (bl, loop_start, loop_end);
- --- 3037,3043 ----
- value of the biv must be invariant. */
-
- if (loop_n_iterations != 0
- ! && ! loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]]
- && invariant_p (bl->initial_value))
- {
- increment = biv_total_increment (bl, loop_start, loop_end);
- ***************
- *** 3126,3132 ****
- to be known. */
-
- if (loop_n_iterations != 0
- ! && ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]])
- {
- /* ?? It is tempting to use the biv's value here since these insns will
- be put after the loop, and hence the biv will have its final value
- --- 3115,3121 ----
- to be known. */
-
- if (loop_n_iterations != 0
- ! && ! loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]])
- {
- /* ?? It is tempting to use the biv's value here since these insns will
- be put after the loop, and hence the biv will have its final value
- diff -rNci gcc-2.7.2/varasm.c gcc-2.7.2p/varasm.c
- *** gcc-2.7.2/varasm.c Thu Aug 31 23:02:53 1995
- --- gcc-2.7.2p/varasm.c Tue Jan 23 09:25:32 1996
- ***************
- *** 78,90 ****
-
- /* Number for making the label on the next
- constant that is stored in memory. */
- !
- ! int const_labelno;
-
- /* Number for making the label on the next
- static variable internal to a function. */
- !
- ! int var_labelno;
-
- /* Carry information from ASM_DECLARE_OBJECT_NAME
- to ASM_FINISH_DECLARE_OBJECT. */
- --- 78,90 ----
-
- /* Number for making the label on the next
- constant that is stored in memory. */
- ! /* intel1 */
- ! static int const_labelno = 0;
-
- /* Number for making the label on the next
- static variable internal to a function. */
- ! /* intel1 */
- ! int var_labelno = 0;
-
- /* Carry information from ASM_DECLARE_OBJECT_NAME
- to ASM_FINISH_DECLARE_OBJECT. */
- ***************
- *** 1147,1158 ****
- else
- {
- #ifdef ASM_OUTPUT_ALIGNED_COMMON
- ! ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
- ! DECL_ALIGN (decl));
- #else
- ! ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
- #endif
- ! }
- }
- else
- {
- --- 1147,1169 ----
- else
- {
- #ifdef ASM_OUTPUT_ALIGNED_COMMON
- ! /* intel1 */
- ! #ifdef ALIGN_DFmode
- ! if (DECL_MODE (decl) == DFmode
- ! && DECL_ALIGN (decl)
- ! == (GET_MODE_SIZE (SFmode) * BITS_PER_UNIT))
- ! {
- ! ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
- ! GET_MODE_SIZE (DFmode) * BITS_PER_UNIT);
- ! }
- ! else
- ! #endif
- ! ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
- ! DECL_ALIGN (decl));
- #else
- ! ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
- #endif
- ! }
- }
- else
- {
- ***************
- *** 1168,1179 ****
- else
- {
- #ifdef ASM_OUTPUT_ALIGNED_LOCAL
- ! ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
- ! DECL_ALIGN (decl));
- #else
- ! ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
- #endif
- ! }
- }
- goto finish;
- }
- --- 1179,1201 ----
- else
- {
- #ifdef ASM_OUTPUT_ALIGNED_LOCAL
- ! /* intel1 */
- ! #ifdef ALIGN_DFmode
- ! if (DECL_MODE (decl) == DFmode
- ! && DECL_ALIGN (decl)
- ! == (GET_MODE_SIZE (SFmode) * BITS_PER_UNIT))
- ! {
- ! ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
- ! GET_MODE_SIZE (DFmode) * BITS_PER_UNIT);
- ! }
- ! else
- ! #endif
- ! ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
- ! DECL_ALIGN (decl));
- #else
- ! ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
- #endif
- ! }
- }
- goto finish;
- }
- ***************
- *** 1327,1332 ****
- --- 1349,1362 ----
- from it in get_pointer_alignment. */
- DECL_ALIGN (decl) = align;
-
- + /* intel1 */
- + #ifdef ALIGN_DFmode
- + if (DECL_MODE (decl) == DFmode
- + && DECL_ALIGN (decl) == (GET_MODE_SIZE (SFmode) * BITS_PER_UNIT))
- + {
- + align = GET_MODE_SIZE (DFmode) * BITS_PER_UNIT;
- + }
- + #endif
- if (align > BITS_PER_UNIT)
- {
- if (output_bytecode)
- ***************
- *** 1575,1581 ****
- if (name[0] == '*')
- {
- if (output_bytecode)
- ! bc_emit_labelref (name, 0);
- else
- fputs (&name[1], file);
- }
- --- 1605,1611 ----
- if (name[0] == '*')
- {
- if (output_bytecode)
- ! bc_emit_labelref (name);
- else
- fputs (&name[1], file);
- }
- ***************
- *** 2954,2960 ****
- union {
- union real_extract du;
- struct addr_const addr;
- - struct {HOST_WIDE_INT high, low;} di;
- } un;
- };
-
- --- 2984,2989 ----
- ***************
- *** 2985,3000 ****
- case CONST_DOUBLE:
- value->kind = RTX_DOUBLE;
- if (GET_MODE (x) != VOIDmode)
- ! {
- ! value->mode = GET_MODE (x);
- ! bcopy ((char *) &CONST_DOUBLE_LOW (x),
- ! (char *) &value->un.du, sizeof value->un.du);
- ! }
- ! else
- ! {
- ! value->un.di.low = CONST_DOUBLE_LOW (x);
- ! value->un.di.high = CONST_DOUBLE_HIGH (x);
- ! }
- break;
-
- case CONST_INT:
- --- 3014,3022 ----
- case CONST_DOUBLE:
- value->kind = RTX_DOUBLE;
- if (GET_MODE (x) != VOIDmode)
- ! value->mode = GET_MODE (x);
- ! bcopy ((char *) &CONST_DOUBLE_LOW (x),
- ! (char *) &value->un.du, sizeof value->un.du);
- break;
-
- case CONST_INT:
- ***************
- *** 3198,3203 ****
- --- 3220,3229 ----
- align = (mode == VOIDmode) ? UNITS_PER_WORD : GET_MODE_SIZE (mode);
- if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
- align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
- + /* intel1 */
- + #ifdef ALIGN_DFmode
- + align = (mode == DFmode) ? GET_MODE_SIZE (mode) : align;
- + #endif
-
- pool_offset += align - 1;
- pool_offset &= ~ (align - 1);
- ***************
- *** 3693,3700 ****
- else
- if (size == 4
- && TREE_CODE (TREE_OPERAND (addr_part, 0)) == VAR_DECL)
- ! bc_emit_labelref (IDENTIFIER_POINTER
- ! (DECL_ASSEMBLER_NAME (TREE_OPERAND (addr_part, 0))),
- TREE_INT_CST_LOW (const_part));
- else
- abort (); /* FIXME: there may be more cases. */
- --- 3719,3725 ----
- else
- if (size == 4
- && TREE_CODE (TREE_OPERAND (addr_part, 0)) == VAR_DECL)
- ! bc_emit_labelref (DECL_ASSEMBLER_NAME (TREE_OPERAND (addr_part, 0)),
- TREE_INT_CST_LOW (const_part));
- else
- abort (); /* FIXME: there may be more cases. */
- diff -rNci gcc-2.7.2/version.c gcc-2.7.2p/version.c
- *** gcc-2.7.2/version.c Sun Nov 26 16:20:43 1995
- --- gcc-2.7.2p/version.c Tue Jan 23 09:54:59 1996
- ***************
- *** 1 ****
- ! char *version_string = "2.7.2";
- --- 1 ----
- ! char *version_string = "2.7.2p";
-